Git merge с --squash, сохраняя журнал каждого коммита
Начальный сценарий:
A (master)
\
B - C - D (development)
Что я хочу после слияния --squash:
A - E (master/development)
\ /
B - C - D
На ветке master
, git log
было бы
commit E
Squashed commit of the following:
commit D
commit C
commit B
commit A
Продолжайте развиваться на ветке development
:
A - E (master)
\ / \
B - C - D F - G - H (development)
Слить с тыквой снова:
A - E - I(master/development)
\ / \ /
B - C - D F - G - H
На ветке master
, git log
было бы
commit I
Squashed commit of the following:
commit H
commit G
commit F
commit E
Squashed commit of the following:
commit D
commit C
commit B
commit A
На ветке development
, git log
было бы
Commit I
Commit H
Commit G
Commit F
Commit E
Commit D
Commit C
Commit B
Commit A
Я хотел бы объединиться с коммитами, раздавленными на master
сохраняя каждый коммит на development
,
Я понятия не имею, как это реализовать. Моя проблема в том, что я не знаю, как сделать D
указать на E
в первом слиянии, и I
будет включать B,C,D,E,F,G,H
вместо F,G,H
только.
3 ответа
Вы не можете получить желаемый результат журнала со структурой, которую вы показали (git log --merges master
вроде как сделаю). Структура, которая даст вам журнал, который вы хотите, побеждает точку. И, в конце концов, это саморазрушительный способ работы с Git.
Желание уметь бегать git log master
и только увидеть сдавленные коммиты. Это не сработает. Git не знает, что некоторые коммиты предназначены для master
а некоторые для development
, Давайте посмотрим на предложенную структуру.
A - E - I [master] [development]
\ / \ /
B - C - D F - G - H
С этой точки зрения, master
а также development
указать на тот же коммит. Что касается истории Git, они идентичны. Ветвь - это не что иное, как метка, указывающая на коммит. Комитеты не помнят, какой отрасли они были привержены. git log master
а также git log development
будет выдавать те же журналы, показывающие все коммиты от A до I. Журналы коммитов E и I будут уничтожены.
Вы можете получить то, что вы хотите с git log --merges master
(или же development
) показывать только коммиты слияния, но это покажет любые коммиты слияния, даже те, что были выполнены как часть development
, Так что на самом деле это не работает.
Вся эта идея излишне сложна, читайте дальше.
Чтобы получить желаемый результат журнала, вы должны разорвать отношения между двумя ветвями, как это.
A - E - I [master]
\
B - C - D - F - G - H [development]
Что вы можете сделать работу как-нибудь, но нет никакого смысла. git log master
содержит все те же сообщения журнала, так что это будет так же долго, как git log development
, но они будут разбиты вместе. Вы не можете использовать git log master
делать археологию кода (то есть "почему эта строка была написана таким образом"), потому что все изменения сведены воедино в одну разницу, что затрудняет сопоставление строки изменения с конкретным сообщением фиксации. Так как история master
а также development
не связан, нет способа гарантировать, что все в процессе разработки превращается в мастер или наоборот (например, горячие исправления в мастер).
git log master
предоставляет меньше информации, чем git log development
и это сложнее понять. master
не имеет отношения к development
и теряет все преимущества сохранения истории слияния. Нет смысла поддерживать эту сложную установку.
Вместо этого используйте git merge --no-ff
объединять ветви функций (а не одну непрерывную ветку "разработки") и хранить историю ветвей для упрощения археологии.
G - J [feature/tacos]
/
A - E - K [master]
\ / \ /
B - C - D F - H - I
E и K - нормальные коммиты слияния, производимые git merge --no-ff
, Там нет непрерывного development
ветвь, которая обрабатывается функциональными ветвями. Функциональные ветви одноразовые и удаляются после объединения. Информация о функциональных ветвях сохраняется в коммите слияния и git merge --no-ff
гарантирует сохранение отраслевой структуры. feature/tacos
это ветка функций для работы с тако, которая еще не была объединена.
git log --graph --decorate master
покажет полную историю мастера с коммитами слияния, показывающими, когда объекты закончились, плюс строки, иллюстрирующие историю ветвлений. Графический инструмент Git с графическим интерфейсом, такой как GitX, является еще одним способом чтения истории в виде графика.
В конце концов, история Git - это график. Если вы научитесь работать с этим графиком, жизнь с Git будет намного проще. Если вы пытаетесь сделать историю Git линейной, как большая стопка блинов, вы побеждаете цель Git и создаете дополнительную работу для себя и всех остальных.
Ну, невозможно получить именно то , что вы просите, так как если вы объединяете ветви, вы все равно увидите коммиты из обеих веток в вашем журнале коммитов. То, что вы могли бы хотеть что-то вроде этого:
A - E (master)
\
B - C - D (development)
Вы просто выбираете коммиты из development
ветви, раздавите их и нанесите поверх master
,
Самый простой способ получить это что-то вроде этого:
git checkout development && git rebase -i master HEAD
Затем вы заменяете все действия, кроме первого, на squash
, В результате вы получите отдельную голову, которая указывает на сдавленный коммит, примененный поверх master
, Вам просто нужно сбросить master
к этому коммиту и все готово.
Я предполагаю, что сообщение коммита будет не совсем тем, что вы хотели, так как оно будет перезаписывать сообщения коммитов всех коммитов, а не их хэши, но вы сможете подключиться к генерации сообщений коммита с --exec
вариант.
Все слишком ручное, но вы можете написать все и создать псевдоним. Я считаю, что это самое близкое, что вы можете использовать git
сам по себе, и не переписывать все на каком-то языке программирования более высокого уровня.
Это обычное слияние...
#!/bin/sh
git init
touch a; git add a; git commit -m a
git checkout -b patch
touch b; git add b; git commit -m b
touch c; git add c; git commit -m c
git checkout master
git merge --no-ff patch
git log --graph --oneline
Результат
* a9fbaec Merge branch 'patch'
|\
| * fb7eac4 c
| * 94f44c1 b
|/
* 4de57a5 a