Git объединяется с --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.


person Zizheng Wu    schedule 17.10.2015    source источник
comment
почему ты хочешь сделать это? Кажется, это усложняет историю. Также результаты вашего журнала не будут такими, как вы думаете. Журнал master покажет все коммиты.   -  person Schwern    schedule 18.10.2015


Ответы (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, чтобы объединить ветви feature (а не одну непрерывную ветвь «разработки») и сохранить историю ветвей для упрощения археологии.

              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 и создадите дополнительную работу для себя и всех остальных.

person Schwern    schedule 17.10.2015

Что ж, невозможно получить в точности то, что вы просите, так как если вы объединяете ветки, вы все равно увидите коммиты из обеих веток в своем журнале фиксации. Возможно, вам понадобится что-то вроде этого:

A      -     E (master)
 \         
 B - C - D (development)

Вы просто выбираете коммиты из ветки development, раздавливаете их и применяете поверх master.

Самый простой способ получить это примерно так:

git checkout development && git rebase -i master HEAD

Затем вы заменяете все действия, кроме первого, на squash. В результате вы получите отделенную головку, указывающую на сжатую фиксацию, примененную поверх master. Вам просто нужно сбросить master на эту фиксацию, и все готово.

Я предполагаю, что сообщение фиксации будет не совсем тем, что вы хотели, так как оно будет резорбировать сообщения фиксации всех коммитов, а не их хэши, но вы сможете подключиться к генерации сообщения фиксации с помощью параметра --exec.

Все слишком вручную, но вы можете создать сценарий и создать псевдоним. Я считаю, что это самое лучшее, что вы можете получить, используя сам git, а не переписывая все на каком-то языке программирования более высокого уровня.

person kirelagin    schedule 17.10.2015

Это обычное слияние ...

#!/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
person Steven Penny    schedule 17.10.2015
comment
Но у вас коммиты не сжаты в ветке master git log - person Zizheng Wu; 18.10.2015
comment
спасибо, что указали на это, я отредактировал свой вопрос, надеюсь, будет понятнее - person Zizheng Wu; 18.10.2015