gpt4 book ai didi

git - Git分支分割点

转载 作者:太空狗 更新时间:2023-10-29 13:53:21 25 4
gpt4 key购买 nike

我在清理git历史树时遇到问题。
基本上,我的git存储库有一个分支,看起来像:

A--B--C--D--E--F--G--H--I--Z--X--Y...   master
\
F--G--H--I--J--K--L... branch1

提交e是一些不重要的更改,可以使其成为多余的。
这里正确的分割点应该是i而不是d。
提交e可以被删除或添加到两个分支。
有什么办法可以做到这一点吗?
----更新
哇,非常感谢你的帮助!
我已经尝试了探路者的建议,而且效果很好!
现在。。我还有另一个仓库要清理,但更复杂。
看起来像:
1--2--3--4--*A--5--6--7--8--*B--9--10--11--*C--*D--12--13--14            master
\
5--6--7--8--9--10--11--12--13--14 branch1

注1:字母表示提交的内容
注2:*信函提交仅适用于主分行
有没有办法清理这样一棵历史树?
另外,对于这种结构的项目,推荐的git方法是什么?
即在分支之后,除了某些特定于分支的提交之外,大多数提交都将包含相同的更新

最佳答案

首先,+1表示绘制提交图的问题。:-)第二,不是很重要,但你可能应该把它看作两个分支,masterbranch1master没有什么特别之处,它只是一个分支,与其他分支一样。1
现在,git中所有内容的核心是您永远不能更改提交。这源于git实际命名每个提交的方式,2使用了难看的40个字符sha-1:sha-1是通过计算提交内容的加密校验和而生成的。因此,如果您(尝试)更改任何内容,“真实名称”将更改,您将有一个新的和不同的提交。
相反,您可以做的是将一个旧的提交复制到一个新的提交,在提交完成之前进行所需的更改(因此给出了它的“真实名称”)。我们在这里要做的就是复制。
你画了这个图:

A--B--C--D--E--F--G--H--I--Z--X--Y...   master
\
F--G--H--I--J--K--L... branch1

但这并不完全正确,因为每个提交都指向其父提交,3这里 F在我们看 E时指向 master,而 F在我们看 D时指向 branch1。(我在这里假设每个字母代表给定提交的sha-1“真实名称”)我将假设当前在 branch1上的那些是副本,尽管这并不重要,只要您对与这些提交相关联的树感到满意(即,当您 git checkout其中一个提交时,您将得到什么)。
你想要的是这样的:
A--B--C--D--E--F--G--H--I--Z--X--Y...   master
\
J'-K'-L'... branch1

这里 J'K'L'中的“prime”标记表示这些是提交 JKL的副本。
我在写这个答案的时候,有几个人建议使用 git cherry-pick来制作这些副本。这很好,但事实上,我们可以使用 git rebase来完成这项任务,因为 cherry-pick是一把简单的斧头,你可以用它来砍倒一棵樱桃树, rebase是一把全自动链锯,你可以用它一举完成所有任务。
我们首先告诉 rebasebranch1进行操作;简单的方法是 git checkout branch1(或者我们可以将 branch1作为最后的参数添加到 git rebase,但我将使用“简单的方法”)。
接下来,我们需要知道我们希望提交从哪里分支,也就是说,有一些方法来命名commit I。从上面,我们可以说 master~3:从 master(其名称为commit Y)中倒数四次提交,然后逐步进行 X,然后再进行 Z,然后到达 I。或者你可以用真名sha-1来做,它总是有效的,但通常需要剪切和粘贴才能完成。对于下面的命令,我只编写 I。我们会告诉瑞贝斯去基地。
最后,我们需要让 --onto选择要复制的提交 rebaseJK。也有很多方法可以做到这一点。也许最简单的方法是使用 L,它将提供对 git rebase -i上的所有内容的重新平衡,然后您可以删除前四个提交的 branch1行。或者,我们可以告诉 pick排除特定提交,但我假设您将使用交互式方法。
因此,这里的最终命令是 rebase(在执行 git rebase -i --onto I master命令之后)。 git checkout branch1使此交互,以便您可以删除提交; -i--onto将选中的新提交系列选择目标; rebase部分告诉 master要排除的提交:具体来说,从名称 rebase中可以到达的任何提交。(这不包括提交 masterABC,但不包括 D上出现的复制版本 F'G'H'I':您只需删除这些版本的“pick”行)。
branch完成一系列的 git rebase命令后,它做的最后一件事是将当前分支( git cherry-pick)的分支标签移动到tip most new commit。所以这确实产生了:
A--B--C--D--E--F--G--H--I--Z--X--Y...   master
\
J'-K'-L'... branch1

如果一切顺利的话。(如果情况不好,可以 branch1停止该过程,并将所有内容恢复到开始之前的状态。)
我们可以更喜欢(假设 git rebase --abortI')做:
git rebase --onto master~3 branch1~3 branch1

甚至没有任何初始的 branch1~3,但这里假设倒数3是正确的(对于 git checkoutmaster)。这与之前基本相同,有三个修改:
我们在末尾添加 branch1以使 branch1作为第一步检查
我们使用 rebase而不是 branch1~3作为参数,表示“排除此内容,只重新设置从此处无法访问的内容”
我们删除了 master,因为这次不需要编辑掉“pick”命令
这需要对提交进行更仔细的计数,以确保所有 -i表达式都是正确的(或者,您也可以通过原始sha-1 id来完成这项工作)。
1好吧,关于 ~,有一些特别的东西:首先,当您执行 master操作时,它是您放置的分支,它创建了一个新的存储库。另一个是 git init稍微调整合并消息。但这两个都是微不足道的。
实际上,git存储库中的四种对象(commit、tree、annotated tag和“blob”(最后一种存储文件内容)都是这样的。每一个都存储在存储库中,然后给出一个由自己的加密校验和组成的名称。
3更准确地说,每个提交都有零个或多个 git merge行,每个 parent ...都给出相应父提交的sha-1 id。第一个父级通常是分支的“主线”,任何其他父级都表示这是合并提交。没有父级的commit,如上面的 parent,是一个“根commit”。

关于git - Git分支分割点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25563797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com