如何比较 Git 中的变更集?

发布于 2024-10-17 20:12:23 字数 195 浏览 3 评论 0原文

Git 可以非常轻松地比较提交之间的差异,例如使用 git 命令 diff 和 difftool。同样在 TortoiseGit 中,您只需选择两个提交来比较它们。

但是有没有办法比较变更集?换句话说:查看一组提交的差异与另一组提交的差异之间的差异。

这对于比较精心挑选的或已重新确定基础的(组)提交非常方便。

Git makes it very easy to compare differences between commits, using for instance the git commands diff and difftool. Also in TortoiseGit you just select two commits to compare them.

But is there a way to compare changesets? In other words: to see the differences between the diffs of one set of commits and the diffs of another set of commits.

This would be very handy to compare (sets of) commits which are cherry-picked or have been rebased.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

原谅我要高飞 2024-10-24 20:12:23

也许 diff <(git show rev1) <(git show rev2) 会做你想要的?

Perhaps diff <(git show rev1) <(git show rev2) will do what you want?

南城旧梦 2024-10-24 20:12:23

我认为一般来说,为了得到你想要的东西,你必须进行某种合并/变基操作才能创建一些东西来比较。

当你真正思考它时,变更集之间的差异的想法是模糊的。我假设您处于这样的情况:

[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'" ]

不过,重新设置基准并不总是最有趣的,我可以想出一个小方法来解决这个问题。假设您适当地解决了冲突,变基的结果工作树应该与合并的结果相同:

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

因此您可以执行该临时合并,并将生成的提交与其他变更集的最终提交进行比较。这会比进行 rebase 快得多。 (无论哪种方式,您当然都会使用一次性分支,而不是变更集 2 的真正分支。)

I think that in general to get what you want, you'll have to do some sort of merge/rebase operation in order to create something to compare with.

When you really think about it, the idea of a diff between changesets is fuzzy. I'm assuming here that you're in a situation like this:

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

So what does it mean to compare those two? Maybe in your case, the diffs in the other history are completely disjoint from those of the two changesets, but in general, the contents of changeset 1 may depend on that other history! This means that there's no good general way for git to perform an operation like this; to do it properly, it'd have to essentially say "what would the difference between the two end commits be if I rebased?" In other words, I believe that the only reasonable definition of the diff between the changesets is the diff between the resulting end commits if they're rebased to have a common ancestor. And of course, if that's what you want, then you'll have to perform an operation in the work tree - there's no other way to muck around with diffs like this. The obvious thing to do would be to rebase, and compare the new endpoints (branches):

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

Rebases aren't always the most fun, though, and I can think of one little way to work around this. The resulting work tree of the rebase, assuming you resolve conflicts appropriately, ought to be the same as the result of a merge:

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

So you could perform that temporary merge, and compare the resulting commit to the end commit of the other changeset. That'll be a lot faster than doing the rebase. (Either way, you'll of course use a throwaway branch, not the real one for changeset 2.)

好多鱼好多余 2024-10-24 20:12:23

以下是我比较两个变更集的方法:

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 命令的结果为空,则变更集是相同的。否则你会看到两个差异之间的差异。

Here's what worked for me to compare two changesets:

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

If the result of the diff command is empty, the changesets are the same. Otherwise you'll see the difference between the two diffs.

演多会厌 2024-10-24 20:12:23

扩展 jeff-bradberry 的答案:

比较两个单一提交引入的变更集:

diff <(git show -U0 <sha-A>) <(git show -U0 <sha-B>)

比较变更集由两个提交序列引入:

diff <(git show -U0 <sha-A>...<sha-B>) <(git show -U0 <sha-C>...<sha-D>)

注意:-U0 是为了避免比较“上下文”行(即在编辑过程中发生更改的行,但不是直接由编辑更改的行)。

Expanding on jeff-bradberry's answer:

To compare the changesets introduced by two single commits:

diff <(git show -U0 <sha-A>) <(git show -U0 <sha-B>)

To compare the change sets introduced by two sequences of commits:

diff <(git show -U0 <sha-A>...<sha-B>) <(git show -U0 <sha-C>...<sha-D>)

Note: -U0 is to avoid comparing "context" lines (i.e. lines that have changed around your edits, but not directly by them).

君勿笑 2024-10-24 20:12:23

从 2.19 开始,我们有了 git radge-diff。正是为了这个目的。

Starting 2.19 we have git radge-diff. It is exactly for that.

陌生 2024-10-24 20:12:23
git diff end_rev_1...end_rev_2

摘自:http://www.kernel.org/pub/软件/scm/git/docs/gitrevisions.html

类似的符号 r1...r2 被称为
r1 和 r2 的对称差和
定义为 r1 r2 --not $(git
合并基础 --all r1 r2)。这是一套
可从以下位置访问的提交数
r1 或 r2 之一但不是来自
两者皆有。

并来自 git diff help:

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.

这对你有用吗?

git diff end_rev_1...end_rev_2

Taken from: http://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html

A similar notation r1...r2 is called
symmetric difference of r1 and r2 and
is defined as r1 r2 --not $(git
merge-base --all r1 r2). It is the set
of commits that are reachable from
either one of r1 or r2 but not from
both.

And from git diff help:

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.

Does that work for you?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文