Сложное слияние и метки. Командная строка
Метки (теги)
Указатели на коммиты, лежат в .git/refs/tags/
- Выступают в роли commit-ish (как commit ID, ветки и ссылки относительно HEAD)
Можно запушить с ключом --tags (но по умолчанию локальны)
Аннотированные теги — объекты в .git/objects/**/
git tag [commitish] -a тег -m Аннотация
- Можно подписывать электронной подписью
Две роли тегов: информационная и управляющая (особенно подписанных)
Сложное слияние
При merge и rebase могут возникать конфликты: в двух историях изменён один и тот же контекст:
- Создадим заведомо конфликтующий коммиты на двух ветках
1 git init 2 python3 -m profile -m difflib > text.txt 3 git add .; git commit -m "Initial profile" 4 cp text.txt ~/tmp/text-0.txt 5 git branch new 6 python3 -m profile -m difflib > text.txt 7 git commit -a -m "Master profile" 8 cp text.txt ~/tmp/text-master.txt 9 git checkout new 10 python3 -m profile -m difflib > text.txt 11 git commit -a -m "New profile" 12 cp text.txt ~/tmp/text-new.txt
- Итак, у нас есть три состояния файла:
text-0.txt (общий предок)
text-master.txt
text-new.txt
git diff HEAD^ на обеих ветках покажет изменения примерно в одних и тех же местах
- ⇒ следовательно, при слиянии будут конфликты
- Попробуем объединить:
1 $ git merge master 2 Auto-merging text.txt 3 CONFLICT (content): Merge conflict in text.txt 4 Automatic merge failed; fix conflicts and then commit the result. 5 git status 6 On branch new 7 You have unmerged paths. 8 (fix conflicts and run "git commit") 9 (use "git merge --abort" to abort the merge) 10 11 Unmerged paths: 12 (use "git add <file>..." to mark resolution) 13 both modified: text.txt 14 15 no changes added to commit (use "git add" and/or "git commit -a") 16
Файл text.txt содержит вставки вида:
12 0.000 0.000 0.000 0.000 sre_parse.py:295(_class_escape) 49 0.000 0.000 0.000 0.000 sre_parse.py:355(_escape) 22 0.000 0.000 0.000 0.000 sre_parse.py:432(_uniq) <<<<<<< HEAD 57/22 0.001 0.000 0.015 0.001 sre_parse.py:435(_parse_sub) 64/22 0.004 0.000 0.014 0.001 sre_parse.py:493(_parse) ======= 57/22 0.001 0.000 0.016 0.001 sre_parse.py:435(_parse_sub) 64/22 0.005 0.000 0.015 0.001 sre_parse.py:493(_parse) >>>>>>> master 22 0.000 0.000 0.000 0.000 sre_parse.py:76(__init__) 88 0.000 0.000 0.000 0.000 sre_parse.py:81(groups) 22 0.000 0.000 0.000 0.000 sre_parse.py:84(opengroup) 4 0.000 0.000 0.000 0.000 sre_parse.py:861(_parse_flag
- Это т. н. 3-way diff по схеме «общий предок + конфликтующие изменения»
Все неконфликтующие изменения из обеих веток применены
HEAD — это содержимое текущей ветка, master — с чем мержим
было бы неплохо ещё знать, что раньше-то было, но тут не показывается
Все "<<<<<<<", "=======" и ">>>>>>>" надо убрать (и ненужные изменения тоже)
- Получится merge commit с изменением, неравным тому, что делалось на ветках
Если вас удовлетворяют изменения, проделанные на одной ветке, можно просто git checkout master text.txt
Когда всё готово, делаем git commit -a
Если в историях больше одного коммита, merge надо продолжить с помощью git merge --continue
Если вы окончательно запутались (особенно в многокоммитных мержах), всё можно откатить назад с помощью git merge --abort
Mergetool
Инструмент, в котором есть , имеет общее название «merge tool».
Список: git mergetool --tool-help
- Запускается вместо ручного исправления конфликтов
*vimdiff показывает четыре окна:
«Эта» ветка (LOCAL)
Общий предок (BASE)
«Та» ветка (REMOTE)
Файл с конфликтами (его и надо исправлять)
Могут остаться backup-файлы, их надо удалить git clean -f
- Другие утилиты позволяют «накликивать» изменения)
TODO пример использования на питоновой программе
- Какая-то программа
- В двух ветках
- переименуем некоторые объекты в каждой
- сделаем неконфликтное изменение (например, добавим комментарий)
- И mergetool!
Организация командной строки
На Windows не работает, замена — pyreadline3
- Просто проимпортить, и уже)
Есть urwid, модный prompt-toolkit и т. п., но это уже оверкилл
shlex — это split / join / quote для командной строки, похожей на shell
- см. примеры
cmd — собственная командная строка!
- Организует REPL
class commandline(cmd.Cmd): — и поехали!
Можно обмазать readline или любым другим враппером
do_COMMAND(строка)
COMMAND — команда
префиксгdocstring — это встроенный help()
строку можно распарсить shlex-ом или более сложным парсером
complete_COMMAND(префикс, строка_целиком, начало_префикса, конец_префикса)
префикс — что достраиваем (введённый текст от конца команды до курсора)
строка_целиком — всё, что успели ввести (вместе с командой и текстом после курсора)
начало_префикса, конец_префикса — индекс префикса в строке_целиком (мало ли, может надо проверить команду или что после курсора)
TODO пример
- Организует REPL
Д/З
Поисследовать pynames (пример на странице проекта, но скорее всего придётся читать и исходники)
- Написать интерпретатор командной строки с достраиванием (completion), который позволяет
- Генерировать имя
произвольногй расы с произвольным подклассом (подклассы есть, например, в generators.elven и в generators.iron_kingdoms; если подкласс не указан, выбирается первый)
- с необязательным указанием пола (male, female, по умолчанию — male, как в API)
- Задавать язык для всех генераторов
- В API он передаётся вторым параметром в генератор
Значение по умолчанию — native)
Если генератор не поддерживает установленный язык, используется native
- Получать информацию о конкретном генераторе (количество имён обоих полов и список языков)
- Формат команд:
language RU
generate mongolian female
Квутух
generate iron_kingdoms Gobber
Vog-Kat-Ad-gamun
generate elven Warhammer
Торрион
info scandinavian male
1239
info scandinavian
1599
info scandinavian language
en ru
Обратите внимание на то, что имя расы совпадает с именем модуля, а имя подкласса — с префиксом имени генератора. В примере выше generate iron_kingdoms Gobber выглядит так, потому что существует генератор pynames.generators.iron_kingdoms.GobberFullnameGenerator()
- ⇒ достраивание можно сделать на несложном исследовании пространств имён модулей
например, выбрать оттуда классы вида Что-то-тамКак-тоGenerator, и выкинуть из этого списка базовые классы, которые автор зачем-то положил прямо рядом с настоящими генераторами
- это же исследование даст нам список рас — модулей, в которых есть такие классы
- Генерировать имя
Разработку вести согласно дисциплине оформления коммитов в подкаталоге 04_MergetoolCommandline отчётного репозитория по Д/З