Что такое команда git для просмотра только тех коммитов, которые внесут изменения?
Не существует. Вы можете приблизить один (см. Ниже), но это опасная дорога.
По сути, проблема здесь в том, что после слияния в сквош вы должны прекратить использовать все коммиты, которые были объединены в сквош, т. Е. Полностью убить ветку, объединенную в сквошЕсли вы продолжаете использовать ветку, вам решать, как с этим справиться: Git не поможет вам.
Помните, что git merge
работает:
- поиск базы слияния;
- в действии, выполнение двух
git diff
с от базы слияния до каждого конца ветви; - объединение результирующих изменений;и
- фиксация результата, запись обоих родителей, так что слияние next использует другую базу слияния.
Изменение этого с помощьюgit merge --squash
сохраняет все вышеперечисленное , за исключением , что последний шаг - заключительная фиксация - (1) отключается, как если бы --no-commit
и (2) выполняются без записи обоихродителей, так что слияние next будет иметь ту же базу слияния.
Поэтому повторное слияние в будущем рассчитывает на шаг «объединения», который позволяет увидеть любые ранее слитые изменения какдублирование и дедупликация их. Это имеет тенденцию работать с небольшими изменениями и не работать с большими.
Имея это в виду, давайте рассмотрим пример случая. Мы начнем с этой истории:
...--o--*--A------B <-- mainline
\
C--D--E--F <-- feature
Если бы в этот момент мы выполнили обычное слияние feature
с mainline
, мы бы получили:
...--o--*--A------B--G <-- mainline
\ /
C--D--E--F <-- feature
где базой слияния был коммит *
, а двумя кончиками ветвей были коммиты B
и F
. Git объединил изменения-с- *
-at- B
с изменениями-с- *
-at- F
, чтобы сделать G
.
Теперь мы можем продолжить разработку feature
добавив больше коммитов. Будущее git merge
использует в качестве базы слияния commit F
, а не commit *
.
Но если мы вместо этого используем git merge --squash
, мы получим этот график:
...--o--*--A------B--G <-- mainline
\
C--D--E--F <-- feature
Ничего не стоит помнить, что коммит F
был тем состоянием, которое feature
имел, когда мы делали коммит G
. Итак, в будущем, когда у нас будет:
...--o--*--A------B--G-----K <-- mainline
\
C--D--E--F--H--I--J <-- feature
, мы не сможем узнать, что "интересные" коммиты H-I-J
(и, конечно, K
)).
Вы должны убить ветку feature
при сквош-слиянии, так что теперь у вас есть:
...--o--*--A------B--G------K <-- mainline
\
H--I--J <-- feature2
Теперь ясно, что "интересные" коммиты H-I-J
(иK
). В качестве альтернативы, не используйте squash-merge: просто выполните обычное слияние, чтобы у вас было:
...--o--*--A------B--G-----K <-- mainline
\ /
C--D--E--F--H--I--J <-- feature
и снова все понятно - ну, это как минимум Git;вы можете использовать feature..mainline
, чтобы найти это с помощью Git - что интересные коммиты H-I-J
(и K
).
Приблизительно, если вы настаиваете
Теперь вы можетеесли хотите, просканируйте весь набор коммитов с C
по J
- то есть на mainline..feature
после вашего более раннего сквош-слияния - и попробуйте выполнить git cherry-pick
каждого такого коммита. 1 В некоторых (простых) случаях Git обнаружит, что сбор вишни C
не имеет никакого эффекта. То же самое относится к D
, E
и F
. G
, H
и I
будут иметь эффект .
Эта концепция ломается во многих реальных случаях. Например, предположим, что commit D
является revert commit C
. В этом случае выбор вишни C
в новую ветвь, происходящую из коммита K
, будет иметь эффект . Вишневое собирание D
поверх него отменит эффект, так как D
- возврат. Вы можете создать инструмент, который обрабатывает этот особый случай, но что, если возврат C
будет E
, а не D
?
GeНеральный случай требует, чтобы слияния были записаны как слияния. Следовательно, общее правило состоит в том, что git merge --squash
"убивает" ветвь. Все его коммиты должны быть отброшены: они были заменены сквош-слиянием;это новая улучшенная форма всех коммитов, соединенных в сквош;их больше никогда не увидят.
1 Вы можете сделать это на новой ветке или на отдельном ГОЛОВЕ, чтобы проверить, действительно ли выбирает вишневый кирчто-нибудь.