git 中跨分支的等效更改的簿记清理

发布于 11-18 23:14 字数 761 浏览 7 评论 0原文

我正在尝试清理大量主题分支,主要是为了使 github 中的 master 分支概述不再因存在相同的更改而在非活动主题分支中显示虚假的“n advance”指示符。

如果没有这些虚假指示器,此概述页面将提供一种很好的方法,可以一目了然地查看旧主题分支中的任何提交是否被无意中错过并且没有合并回 master 中。

在下图中,Y 是分支 topic 中的提交,后来作为 Y' 应用于 master (所以它们有不同的 sha1 哈希值,但补丁 ID 相同)。

A --- B --- C --- Y' --- E    <-- master
       \ 
        X --- Y               <-- topic

gitcherrymastertopic 适当地报告:

- Y

但是,如果我尝试通过从 master 发出 git mergetopic 来清理它,我会遇到合并冲突自从 master 中的更改 E 改变了应用补丁的上下文。

有没有办法告诉master“嘿,你确实已经有了Y,所以你可以停止报告你没有。”? (能够以自动/编程方式应用的方式做到这一点是关键。)

I'm attempting to cleanup a large number of topic branches, primarily so that the branch overview for master in github no longer displays spurious "n ahead" indicators in inactive topic branches due to the presence of identical changes.

Without these spurious indicators, this overview page would offer a great way to see at a glance if any commits from old topic branches were inadvertently missed and not merged back down into master.

In the diagram below, Y is a commit in branch topic that was later applied to master as Y' (so they have different sha1 hashes, but identical patch ids).

A --- B --- C --- Y' --- E    <-- master
       \ 
        X --- Y               <-- topic

git cherry master topic appropriately reports:

- Y

But if I try to clean this up by issuing a git merge topic from master, I get a merge conflict since change E in master has since altered the context against which the patch applied.

Is there a way to tell master "Hey, you really do have Y already, so you can stop reporting that you don't."? (Being able to do this in such a way that it could be applied automatically/programmatically is key.)

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

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

发布评论

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

评论(3

锦欢2024-11-25 23:14:16

您可以通过将 --cherry-pick 选项传递给 git log 来查看分支之间修订的有效差异。

我最喜欢的咒语是:(

git log --left-right --graph --cherry-pick --oneline branch1...branch2

我的别名git lr)。

来自 手册页

<前><代码>--cherry-pick

当提交集受到对称差异限制时,忽略与“另一侧”的另一个提交引入相同更改的任何提交

例如,如果您有两个分支 A 和 B,仅在其中一侧列出所有提交的常用方法是使用 --left-right (请参阅下面的示例) --left-right 选项的描述)。然而,它显示了从另一个分支中精心挑选的提交(例如,“b 上的 3rd”可能是从分支 A 中精心挑选的)。 使用此选项,此类提交对将从输出中排除

<前><代码>--cherry-mark

--cherry-pick 类似(参见下面上面),但使用 = 标记等效提交,而不是省略它们,以及不等价的 +


永久解决方案#1

为了永久地让 git 不再担心实际上是精心挑选的提交,您可以随时合并其他分支。合并提交将被标记为前一个提交和合并修订树的尖端子修订

这告诉修订树遍历在该点停止遍历历史记录。只有当合并来自“其他”分支的修订版时,这样做才是安全的,IFF 你**知道它的所有父项都已被合并(只要你希望它们合并)。

永久解决方案#2

还有一些使用移植的方法。这实际上意味着您将告诉 git - out of band1 - 那某个修订版是另一个修订版的子版本,无需实际重新建立基础/从中合并。

1 就像一个带有 sha1 哈希值对的手写文件:)

这样做的好处是,您不必重写历史记录才能使其发挥作用。但是,如果您愿意,可以使用 git filter-branch使移植物永久。那么您就不再需要grafts文件了,但是,当然,您将面临必须重写历史记录(并且可能使已发布的修订ID无效)的缺点。

未解决问题?

如果所有其他方法都失败了,有时您可能会陷入经常想要合并的远程(主题)分支,但有些差异您根本不想接受。这些可能会一遍又一遍地导致相同的合并冲突。

在这种情况下,我只需指向 git-rerere (重用记录的冲突合并解决方案),这可以使生活变得更加容易,尽管更复杂

You can see the effective difference in revisions between branches by passing the --cherry-pick option to git log.

My favourite incantation runs:

git log --left-right --graph --cherry-pick --oneline branch1...branch2

(which I have aliases as git lr).

From the man page:

--cherry-pick 

Omit any commit that introduces the same change as another commit on the "other side" when the set of commits are limited with symmetric difference.

For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right (see the example below in the description of the --left-right option). It however shows the commits that were cherry-picked from the other branch (for example, "3rd on b" may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.

--cherry-mark 

Like --cherry-pick (see belowabove) but mark equivalent commits with = rather than omitting them, and inequivalent ones with +.


Permanent solution #1

In order to permanently make git stop worrying about commits that were actually cherry-picked, you can always merge the other branh. The merge commit will be marked as a child revision of both the previous commit and the tip of the merged revision tree.

This tells the revision tree traversal to stop walking the history at that point. Doing so would only be safe when merging a revision from the 'other' branch IFF you **know that all it's parents have been merged (as far as you would ever want them merged).

Permanent solution #2

There is also some way to use grafts. This really means nothing more than that you'll tell git - out of band1 - that a certain revision is a child of another revision, without having to actually rebase onto/merge from it.

1 as in, a handwritten file with pairs of sha1 hashes :)

The positive thing about this is that you don't have to rewrite history for this to work. However, if you want to, you can use git filter-branch to make the grafts permanent. You no longer need the grafts file then, but of course, you'll be back with the disadvantages of having to rewrite the history (and possibly invalidating published revision ids).

Loose ends?

If all else fails, sometimes you can be stuck with remote (topic) branches that you frequently want to merge from, but there are differences that you simply never want to take. These would probably result in the same merge conflicts over and over.

In that case I'll just point at git-rerere (Reuse recorded resolution of conflicted merges) which can make life considerably easier, albeit more complicated

东北女汉子2024-11-25 23:14:16

由于这是一个公共存储库,因此不想rebase历史记录,这是一种奇怪的回避方式,但请考虑使用revertmerge、和一个计数器恢复

master 上,分别恢复 E 和 Y' 以将 master 恢复到 C 处的状态(提交消息表明您正在引入一个被遗忘的主题分支,而不是删除更改) :

git revert E
git revert Y'

记下 E 的恢复提交的 sha1,或 git tag revert_E sha1 它。

现在,您将能够将您的 topic 合并到 master 上:

git merge topic

此时主题已正确合并,并且 master 返回到 Y 之前的状态/Y',您现在可以恢复 E 的恢复提交来恢复它:

git revert revert_E

这将完全适用,因为 master 处于与您最初提交 E 时相同的状态(该状态的历史刚刚改变)。感觉有点杂技,但可以解决你的问题。我想不出任何更干净的东西。

This is sort of an odd sidestep around not wanting to rebase history since this is a public repo, but consider a solution with revert, merge, and a counter revert.

On master, revert E and Y' separately to restore master to its state at C (with commit messages saying that you are bringing in a forgotten topic branch, not removing changes):

git revert E
git revert Y'

Note down the sha1 of the revert commit for E, or git tag revert_E sha1 it.

Now you will be able to merge your topic onto master:

git merge topic

With topic properly merged at this point, and master returned to its state up to Y/Y', you can now revert your revert commit of E to restore it:

git revert revert_E

which will apply cleanly since master is in the same state it was when you originally committed E (the history to that state has just changed). Feels a bit acrobatic, but would solve your problem. I can't think of anything cleaner.

烟雨扶苏2024-11-25 23:14:16

我不知道为什么我之前没有想到这一点,但只要相同的变更列表是 mastertopic 之间的唯一区别,git merge -s ours topic from master 将轻松解决问题。显然,合并将在没有冲突的情况下应用,并且合并的存在将消除虚假的未合并指示符。

我的 github 分支概述页面现在没有误导性的“n advance”指示器,因此真正的未合并提交将清晰可见。

I'm not sure why I didn't think of this before, but as long as an identical changelist is the only difference between master and topic, git merge -s ours topic from master will easily solve the problem. The merge will obviously apply without conflict, and the presence of the merge will eliminate the spurious unmerged indicator.

My github branch overview page is now free of misleading "n ahead" indicators, so genuine unmerged commits will stick out clearly.

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