Как сравнить изменения в Git?

Git позволяет легко сравнивать различия между коммитами, используя, например, команды git diff и diffftool. Также в TortoiseGit вы просто выбираете два коммита для их сравнения.

Но есть ли способ сравнить changeets? Другими словами: увидеть различия между различиями одного набора коммитов и различий другого набора коммитов.

Это было бы очень удобно для сравнения (наборов) коммитов, которые были выбраны вишней или были переустановлены.

Ответ 1

Возможно, diff <(git show rev1) <(git show rev2) сделает то, что вы хотите?

Ответ 2

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

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

[other history]   [ "changeset 1" ]
o - o - o - o - o ( - o - o - o - o)
 \
  (o - o - o - o - o)
  [ "changeset 2" ]

Итак, что значит сравнивать эти два? Возможно, в вашем случае различия в другой истории полностью не пересекаются с различиями двух наборов изменений, но в целом содержимое набора изменений 1 может зависеть от этой другой истории! Это означает, что нет хорошего общего способа для git выполнить такую ​​операцию; для того, чтобы сделать это правильно, он должен был бы сказать: "Какая разница между двумя конечными коммитами, если я переустановил?" Другими словами, я считаю, что единственным разумным определением разницы между наборами изменений является различие между итоговым завершением, если они переустановлены, чтобы иметь общего предка. И, конечно, если это то, что вы хотите, тогда вам нужно будет выполнить операцию в дереве работы - нет другого способа гадать с такими различиями. Очевидно, что нужно было бы переустановить и сравнить новые конечные точки (ветки):

[other history]   [ "changeset 1" ]
o - o - o - o - o ( - o - o - o - o)
                 \
                  (o - o - o - o - o)
                  [ "changeset 2'" ]

Ребазы не всегда самые забавные, и я могу придумать один маленький способ обойти это. Полученное деревом работы rebase, предполагая, что вы разрешаете конфликты должным образом, должно быть таким же, как результат слияния:

[other history]   [ "changeset 1" ]
o - o - o - o - o ( - o - o - o - o)
 \               \
  \               ------
   \                    \
   (o - o - o - o - o) - X
    [ "changeset 2" ]

Итак, вы можете выполнить это временное слияние и сравнить полученный коммит с окончанием фиксации другого набора изменений. Это будет намного быстрее, чем выполнение rebase. (В любом случае, вы, конечно, будете использовать ветвь с отбрасыванием, а не реальную для changeet 2.)

Ответ 3

Вот что мне удалось сравнить два набора изменений:

git diff [base_sha_a]..[final_sha_a] > ./a.diff
git diff [base_sha_b]..[final_sha_b] > ./b.diff
diff ./a.diff ./b.diff

Если результат команды diff пуст, изменения становятся одинаковыми. В противном случае вы увидите разницу между двумя различиями.

Ответ 4

git diff end_rev_1...end_rev_2

Взято из: http://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html

Аналогичное обозначение r1... r2 называется симметричная разность r1 и r2 и определяется как r1 r2 - не $(gitmerge-base - all r1 r2). Это набор коммитов, достижимых из либо один из r1 или r2, но не из и другие.

И из справки git diff:

git diff [--options] <commit>...<commit> [--] [<path>...]
   This form is to view the changes on the branch containing and up to the second <commit>, starting at a
   common ancestor of both <commit>. "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B".
   You can omit any one of <commit>, which has the same effect as using HEAD instead.

Это работает для вас?