Автоматизировать создание одного коммита из различий между двумя ветками - PullRequest
0 голосов
/ 06 ноября 2019

При работе с компонентом я всегда создаю ветвь элемента из текущей основной ветви (например, «feature / my-feature-name»), а затем объединяю ее с master, как только завершу.

Проблема в том, что я в конечном итоге привожу много бессмысленных «Работ в процессе», чтобы освоить этот путь.

Чтобы избежать этой проблемы, я хотел бы создать новую локальную ветвь функций (например, "feature / my-feature-name-CLEAN"), которая не содержит никаких коммитов, которые я сделал в "feature /my-feature-name ", но имеет различия между feature / my-feature-name и master как незафиксированные изменения. Таким образом, я могу просто зафиксировать эти изменения в "feature / my-feature-name-CLEAN" в одном коммите, а затем объединить его с master.

Нечто подобное описано здесь: git createкоммит из diff между двумя ветвями

Знаете ли вы, есть ли команда git, скрипт или клиентская функциональность Git, которая может сделать это автоматически?

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Существует около трех (или десяти или сотен, в зависимости от того, как вы хотите считать) различных способов сделать это в Git, но, вероятно, самый простой для вашего конкретного случая - это использовать git merge --squash.

Боковая панель: git merge часто выполняет коммиты слияния. git merge --squash никогда совершает коммиты слияния. Это делает git merge --squash вводящей в заблуждение командой. Git использует слияние machinery , чтобы получить результат, но заставляет вас запускать git commit вручную в конце, и в этот момент вы можете предоставить совершенно новое сообщение фиксации.

Давайте проиллюстрируем, как именно это работает. Помните, что Git на самом деле все о коммитах - тех сущностях с большими уродливыми хэш-идентификаторами - и его совсем не волнует имена ветвей , такие как master иfeature/my-feature-name. Имя действительно содержит только один идентификатор хеша коммита. Каждый коммит содержит другой хеш-идентификатор, 1 его непосредственного родительского коммита, так что коммиты могут быть обработаны, начиная с конца и работая в обратном направлении.

Реальный хешИдентификаторы выглядят случайными и непредсказуемыми. Мы будем использовать одиночные заглавные буквы, такие как H, чтобы заменить настоящие хеш-идентификаторы, и будем распределять их последовательно, чтобы было легко увидеть, какой коммит мы сделали, когда. Конечно, это сильно ограничит количество коммитов, которые мы можем сделать (что является , почему Git использует такие большие уродливые хэш-идентификаторы). Мы начнем с самого первого коммита:

A   <-- master

, у которого нет родителя, потому что ранее не было коммита. Имя master указывает на этот коммит (имя master содержит его фактический хэш-идентификатор).

Теперь мы делаем второй коммит. Новый коммит указывает на первый коммит, и Git обновляет имя master, чтобы оно указывало на второй коммит:

A <-B   <-- master

Мы делаем третий, четвертый и т. Д. Коммит и получаемцепочка:

... <-F <-G <-H   <-- master

Имя всегда указывает (содержит хэш-идентификатор) на последний коммит в цепочке. Вот и все, что на самом деле представляет собой ветвь в Git: имя, содержащее идентификатор хеша last commit. Каждый коммит содержит хеш-идентификатор коммита на один шаг назад, и именно так Git-репозиторий хранит history .

Давайте немного ленився и перестанем рисовать внутренние стрелки какстрелки. Это не совсем лень, потому что теперь я хочу начать рисовать имя второй ветви. Мы сделаем новое имя, feature/tall:

...--F--G--H   <-- feature/tall (HEAD), master

Обратите внимание, что оба имени указывают на тот же коммит . Все коммиты, которые находятся в ветке master, находятся в нашей новой ветке, feature/tall. Мы также добавляем слово HEAD в скобках, прикрепленное к одному из этих имен, чтобы мы могли помнить, на какой ветке мы находимся.

Теперь мы делаем новые коммиты, некоторые из которых имеют глупые лайки, такие какwip или my hands are typing words:

...--F--G--H   <-- master
            \
             I--J--K--L--M--N   <-- feature/tall (HEAD)

Мы достигли точки, когда вы хотите получить один единственный коммит, который вы хотите пометить feature/tall-CLEAN. Итак, сначала нам нужно найти хеш-идентификатор commit H. Если master по-прежнему указывает на H, это простой способ найти его. 2 При условии, что это так, вы можете просто сделать:

git checkout -b feature/tall-CLEAN master

, что дает вам следующее:

...--F--G--H   <-- feature/tall-CLEAN (HEAD), master
            \
             I--J--K--L--M--N   <-- feature/tall

Теперь вы можете запустить:

git merge --squash feature/tall

Сравнивает коммит H - коммит, который вы получили прямо сейчас - с коммитом N, чтобы увидеть, что изменилось. Затем те же самые изменения применяются к коммиту H, чтобы подготовиться к созданию нового коммита O.

Чтобы действительно сделать O, вы должны выполнить git commit. Это делает O и перемещает имя feature/tall-CLEAN, чтобы указать на новый коммит:

             O   <-- feature/tall-CLEAN (HEAD)
            /
...--F--G--H   <-- master
            \
             I--J--K--L--M--N   <-- feature/tall

, и вы получите именно то, что хотели.


1 На самом деле, каждый коммит имеет список таких хеш-идентификаторов. Большинство коммитов имеют только одну запись в списке. В коммите слияния есть две или более записей, а самый первый коммит, который вы (или кто-либо другой) делает в новом, пустом репозитории, имеет пустой список - без родительских коммитов - потому что там есть более ранний коммит.

2 Если master больше не указывает на H, вам нужно найти коммит H. Один из способов - запустить git log --graph --oneline --decorate master feature/tall и проверить вывод. Затем вы можете вырезать и вставить его сокращенный идентификатор хеша. Другой способ - использовать git merge-base --all master feature/tall, который должен распечатать хэш-идентификатор H, который вы снова можете вырезать и вставить.

0 голосов
/ 06 ноября 2019

Я полагаю, что интерактивная перебазировка git rebase --interactive <base-commit>, в которой вы раздавите все грязные коммиты, сделает работу.

См. Документ здесь для получения дополнительной информации оварианты перебазирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...