После выполнения слияния, включающего изменения коллег, я хочу, чтобы они описали, что изменилось у каждого из нас, и то, как я разрешил конфликты.
Однако стандартный способ отображения слияний git для этого не подходит, поскольку он показывает только те фрагменты, которые каждый из нас изменил. Поэтому по умолчанию git show MERGE_COMMIT
показывает только то, как были разрешены конфликты слияния вручную.
Что мне нужно: увидеть все изменения, произошедшие с момента расхождения ветвей, даже если не было конфликтов слияния, и приписать их одному из родителей.
git show -c
и -m
недостаточно:
Я выяснил, что есть аргументы git diff-tree
, которые также понимаются git show
, а именно -m
, -c
и --cc
.
--cc
(используется по умолчанию git show MERGE_COMMIT
) не показывает автоматически объединенные фрагменты и новые файлы.-c
Не показывает новые файлы-m
показывает новые файлы, но разделяет две ветви, из-за чего трудно судить, имеет ли объединенный файл семантический смысл.git diff $(git merge-base HEAD^1 HEAD^2) HEAD
(спасибо @ 1615903) не атрибутирует изменения, как опции -c
/--cc
: используя эти два, перед тем, как получить разницу, я получаю по одному столбцу для каждого родителя, поэтому из столбца +
/-
я может сделать вывод, какой родитель внес это изменение.Игрушечный пример. Базовый коммит создает file
, ветка A добавляет несколько строк, ветка B добавляет несколько строк, одна в той же позиции, что и A, создавая конфликт. Кроме того, и A, и B добавляют file_a
и file_b
соответственно:
git init
# Add content to "file" to modify later
for f in `seq 1 15`; do echo "Line $f" >> file; done
git add file && git commit -m "initial commit"
# Divergent branch A: add "change a" to file and add new file_a
sed -i "s/Line 2/Line 2\nchange a/" file
sed -i "s/Line 10/Line 10\nchange a/" file
echo change a > file_a
git add . && git commit -m "change a"
# Divergent branch B: add "change b" to file and add new file_b
git checkout -b dev master~
sed -i "s/Line 14/Line 14\nchange b/" file
sed -i "s/Line 10/Line 10\nchange b/" file
echo change b > file_b
git add . && git commit -m "change b"
git checkout master
git merge dev
## Auto-merging file
## CONFLICT (content): Merge conflict in file
## Automatic merge failed; fix conflicts and then commit the result.
# Create the union -- remove the conflict markers
sed -i "/^[^Lc].*$/d" file
cat file
## Line 1
## Line 2
## change a
## [...]
## Line 10
## change a
## change b
## [...]
## Line 14
## change b
## Line 15
git add . && git commit -m "Merge 'dev' into 'master'"
Стандартный вариант показывает только ту строку, где был конфликт слияния (две ветки изменили одну и ту же строку)
git show HEAD
:
[...]
diff --cc file
index 2fe2e63,019eb18..92b6fb7
--- a/file
+++ b/file
@@@ -9,7 -8,7 +9,8 @@@ Line
Line 8
Line 9
Line 10
+change a
+ change b
Line 11
Line 12
Line 13
С git show -c HEAD
немного лучше, здесь показаны два других куска file
, которые были решены автоматически:
[...]
diff --combined file
index 2fe2e63,019eb18..92b6fb7
--- a/file
+++ b/file
@@@ -1,6 -1,5 +1,6 @@@
Line 1
Line 2
+change a
Line 3
Line 4
Line 5
@@@ -9,9 -8,10 +9,11 @@@ Line
Line 8
Line 9
Line 10
+change a
+ change b
Line 11
Line 12
Line 13
Line 14
+ change b
Line 15
Чего еще не хватает, так это file_a
и file_b
, которые не отображаются.
Это будет git diff $(git merge-base HEAD^1 HEAD^2) HEAD
, который не указывает, из какой ветки пришли изменения. В нем есть только один столбец +/-, поэтому я не знаю, кто из двух авторов ветки что изменил. Отредактировал вопрос, включив в него это, поскольку такой подход является шагом в правильном направлении.
git show -c
дает вам то, что вы хотите, комбинированные различия для обычных модификаций, за исключением того, что он не перечисляет такие вещи, как добавление и удаление, когда нет различий для объединения, поэтому (например) git show -m --oneline --raw
сначала перечислить все изменения, а затем -c
, чтобы покажите комбинированные различия там, где это имеет смысл. Добавьте --diff-filter=m
, чтобы пропустить заголовок, если нет добавлений/удалений, чтобы два набора не перекрывались.
git show -m --oneline --raw; git show -c --oneline`
или
git show -m --oneline --raw --diff-filter=m; git show -c --oneline
Как насчет того, чтобы найти первого общего предка двух (или более) объединенных коммитов и провести сравнение с ним?