Сложное слияние и метки. Командная строка
Метки (теги)
- Указатели на коммиты, лежат в .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».
 , имеет общее название «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 отчётного репозитория по Д/З 
