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
Другие вопросы по тегам