Сравнение различий во вспомогательной памяти в Git
Предположим, что я просто переустановил ветвь foo
на master
, с конфликтами. Я хочу убедиться, что во время разрешения конфликтов я случайно не повредил содержимое foo
, внеся дополнительные изменения или потеряв изменения (отличные от того, что подходит для разрешения конфликта). Я сделал это через:
diff -u <(git diff `git merge-base master [email protected]{1}` [email protected]{1}) \
<(git diff `git merge-base master foo ` foo )
(обновление: или эквивалентный синтаксис ...
для git-diff
, который мне только что напомнили:)
diff -u <(git diff [email protected]{1}) <(git diff master...foo) | mate
Это показывает мне все изменения, произошедшие с master..foo
, рассматриваемые как патч, и именно это я хочу проверить на минимальное. Однако вызов является сложным, и вывод не совсем понятен для интерпретации.
Есть ли лучший способ выполнить эту задачу - предоставить ту же информацию, но с лучшим способом или форматом - или я должен просто взять вышеописанное и обернуть его в script?
Ответы
Ответ 1
То, что мы действительно хотим показать, - это комбинированный diff конфликта, который генерируется так, как будто мы выполнили слияние, чтобы получить от (a) до (b), где (a) ранее было основано (вверх по течению) и (b ) теперь основывается на (восходящем-новом).
Мы не хотим просто прямого разграничения.
Вместо этого мы можем по существу выполнить слияние, но заставляем результирующее дерево быть $b ^ {tree}, которое мы уже знаем, является правильной "конечной" точкой того, что мы хотим.
Более или менее предположим, что мы имеем
newcommit -> the new version of the series
oldcommit -> the old version of the series
upstream -> the (new) version of the base of the series
Мы можем сгенерировать слияние через
git commit-tree newcommit^{tree} -p oldcommit -p upstream -m "message"
а затем показать результат с помощью git show ", и это приведет к созданию объединенного формата diff, который отображает все необходимые биты в качестве разрешения конфликта, который автоматически игнорирует изменения, которые фактически не являются частью разрешения конфликтов.
Это даже работает для простого изменения изменений, и вы можете сделать немного больше работы, чтобы гарантировать, что сгенерированное комманда слияния имеет точные отметки времени автора и фиксации, чтобы она соответствовала нескольким вызовам (так как мы храним свободную ссылку в базу данных объектов).
К сожалению, я не смог понять, как просто получить "git diff", чтобы различать то же самое, не создавая дерева. Я не уверен, какие аргументы нам нужно пройти, чтобы добраться до этой точки.
Ответ 2
Различия между master и rebased foo:
git diff master..foo
против.
Различия pre-rebase foo после разветвления мастера (обратите внимание на три точки):
git diff [email protected]{1}
?
Ответ 3
Так как это rebase, а не слияние, вы можете сравнить foo
с самим собой, но до слияния. Если я правильно назову [email protected]{1}
, вы получите родительский элемент текущей фиксации для foo
, и, возможно, это не то, что вы ищете.
Я думаю, вы можете сделать что-то вроде следующего (если вы не сделали git gc
):
На ветке foo
после rebase:
$ git reflog
Это покажет, как движется ваш филиал HEAD. Вы должны увидеть некоторые записи, подобные этому (в зависимости от того, если вы переустановите интерактивно или нет):
64d3c9e [email protected]{15}: rebase -i (finish): returning to refs/heads/master
64d3c9e [email protected]{16}: rebase -i (fixup): Fixes external dependencies
049169e [email protected]{17}: rebase -i (fixup): updating HEAD
d4c2e69 [email protected]{18}: rebase -i (pick): Fixes external dependencies
049169e [email protected]{19}: rebase -i (fixup): Imports futures
e490bed [email protected]{20}: rebase -i (fixup): updating HEAD
...
etc
...
Посмотрите вперед к последнему фиксации foo
перед слиянием. В зависимости от того, что вы сделали, это может быть сложно или нет. Вот почему я не предоставил do-it script.
Поднимите идентификатор фиксации, который имеет последнюю фиксацию для foo
, перед переустановкой, а затем сравните с этим идентификатором фиксации. Скажем, что идентификатор фиксации: XXXX
:
git diff XXXX...foo
Возможно, это то, что вы хотите.
Ответ 4
git-cherry
ищет коммиты на одной ветке, которые не находятся на другом. Вы использовали бы его как:
git cherry -v OLDTIP TIP UPSTREAM
то есть. найдите коммиты, которые были на OLDTIP
, но не на UPSTREAM..TIP
. Он рассматривает подпись патча, чтобы увидеть, включен ли патч, поэтому, если патч был добавлен, сброшен или изменен во время переустановки, он появится в списке. Вещи, которые были применены без изменений, не будут отображаться.
Аналогичный эффект может быть достигнут, возвращаясь к OLDTIP
и выполняя git rebase -i TIP
, поскольку для этой цели используется одна и та же логика для заполнения списка коммитов.
Ответ 5
Несколько иной подход: Git имеет хорошую поддержку для показа этого в случае слияний. то есть "что изменилось относительно родителя-1, которое не может быть объяснено родителем-2?"
Есть несколько способов, которыми вы могли бы использовать эту поддержку для своей rebase:
Вариант 1:
-
Сначала выполните сбрасывание (вместо переустановки). Затем на дисплее обычного слияния будет показано, что изменилось слияние. Проверьте, что вы хотели.
-
Вернитесь назад и переустановите, и сравните переустановленный отзыв с результатом слияния - они должны быть идентичными.
Вариант 2 (если перезагрузка проще слияния):
- Сделайте перезагрузку.
- Используйте трансплантат, чтобы он выглядел как слияние локально/временно.
Чтобы сделать это, создайте .git/info/grafts с одной строкой:
TIP UPSTREAM OLDTIP
Где TIP - это идентификатор фиксации вашей переустановленной ветки, а остальные - два желаемых родителя (т.е. две вещи, которые вы объединили бы, если бы вы делали слияние). Затем рассмотрите его так, как если бы это было реальное слияние.
Я не уверен в его автоматизации; Я стараюсь делать это с открытым gitk, потому что он упрощает сравнение правильных версий (с помощью контекстного меню).
Если вы действительно хотите сравнить два diff, вы можете посмотреть на interdiff (1), но я не уверен, насколько хорошо он справится с разными файлами базы.