如果不创建一个分支并在一个新分支上做一堆奇怪的工作,那么在将一个提交提交到本地存储库之后,是否有可能将其分解为几个不同的提交?
当前回答
我是用rebase做的。编辑提交对我来说不起作用,因为它已经选择了提交文件并允许您对其进行修改,但我想将所有文件添加为未跟踪的文件,这样我就可以选择其中的一些文件。步骤如下:
git rebase-i HEAD~5(我想拆分我历史上第五次提交)复制目标提交ID(稍后需要)用d标记提交以删除它;在提交之后立即添加一行b,以停止重定基础过程,稍后继续。即使这是最后一次提交,这也为您提供了一些空间,让您只需git rebase——在发生错误时中止并重置所有内容。当重新定基达到断点时,使用gitcherry-pick-n<COMMIT ID>。这将在不选择提交本身的情况下选择提交更改,从而使其未被跟踪。在第一次提交时添加所需的文件(或使用gitadd-i和补丁,以便添加特定的块)提交您的更改。决定如何处理剩余的更改。在我的情况下,我希望他们在历史结束时,没有冲突,所以我做了git stash,但你也可以直接提交。gitrebase—继续选择其他更改
作为一个交互式数据库的超级粉丝,这是我能想到的最简单、最直接的一套步骤。我希望这对任何人都有帮助!
其他回答
git rebase-我会做的。
首先,从一个干净的工作目录开始:git状态应该显示没有挂起的修改、删除或添加。
现在,您必须决定要拆分哪些提交。
A) 拆分最近的提交
要拆分最近的提交,首先:
$ git reset HEAD~
现在,以通常的方式单独提交这些片段,根据需要生成任意数量的提交。
B) 将提交拆分到更远的位置
这需要重新定基,即重写历史。要指定正确的提交,您有几个选项:
如果是三次提交,那么$git rebase-i头~3其中3是返回的提交数。如果它在树上比你想数的更远,那么$git rebase-i 123abcd~其中123abcd是要拆分的提交的SHA1。如果您位于要合并到主节点的其他分支(例如,要素分支)上:$git rebase-i主
当您获得rebase编辑屏幕时,找到您想要拆分的提交。在该行的开头,用edit(简称e)替换pick。保存缓冲区并退出。在您要编辑的提交之后,回扣将立即停止。然后:
$ git reset HEAD~
以通常的方式单独提交各个部分,根据需要生成多个提交。
最后
$ git rebase --continue
大多数现有的答案都建议使用交互式rebase-git rebase-i或类似的方法。对于像我这样害怕“互动”的人来说,下楼梯时喜欢抓住扶手,这里有一个选择。
假设您的历史看起来像…->P–>Q–>R–>…–>Z=mybranch,并且您希望将P–>Q分成两个提交,以P–>Q1–>Q'–>R'–>…Z'=mybranch结束,其中Q'、R'等处的代码状态与Q、R等相同。
在开始之前,如果你是偏执狂,请备份我的分支,这样你就不会冒失去历史的风险:
git checkout mybranch
git checkout -b mybranch-backup
首先,签出P(要拆分的地方之前的提交),并创建一个新的分支来处理
git checkout P
git checkout -b mybranch-splitting
现在,从Q中签出您想要的任何文件,并根据需要进行编辑,以创建新的中间提交:
git checkout Q file1.txt file2.txt
[…edit, stage commit with “git add”, etc…]
git commit -m "Refactored the widgets"
请注意此提交的哈希值,如Q1。现在,在Q1的分离HEAD上检查Q的完整状态,提交这个(创建Q'),并将工作分支向上拉:
git checkout Q
git reset --soft Q1
git commit -m "Added unit tests for widgets"
git branch -f mybranch-splitting
您现在在Q'处执行mybranch拆分,它应该具有与Q完全相同的代码状态。现在将原始分支(从Q到Z)重设为:
git rebase --onto HEAD Q mybranch
现在,mybranch应该看起来像…P->Q1–>Q'–>R'–>…Z',正如您所希望的那样。因此,在检查所有工作正常后,可以删除工作分支和备份分支,并(如果合适)将重写的mybranch推到上游。如果它已经被推了,你需要强制推,所有关于强制推的常见警告都适用。
git push --force mybranch
git branch -d mybranch-splitting mybranch-backup
使用最新提交
如果您只想从现有提交中提取一些内容并保留原始提交,可以使用
git reset --patch HEAD^
而不是git reset HEAD^。此命令允许您重置所需的块。
选择要重置的块后,您将拥有将重置上一次提交中更改的分段块。现在,您更改最后一次提交,从中删除这些更改
git commit --amend --no-edit
您可以通过以下方式将未堆叠的块添加到单独的提交中
git add .
git commit -m "new commit"
不使用最新提交
当然,按照上面的建议,使用gitrebase——interactive来执行之前的一些提交。
离题事实:
在mercurial中,他们有hgsplit——我希望在git中看到hg吸收之后的第二个特性。
这已经过去8年多了,但也许有人会发现它对你有所帮助。我能够做到这一点,而不需要重新启动。其目的是将git引导到与git提交之前相同的状态:
# first rewind back (mind the dot,
# though it can be any valid path,
# for instance if you want to apply only a subset of the commit)
git reset --hard <previous-commit> .
# apply the changes
git checkout <commit-you-want-to-split>
# we're almost there, but the changes are in the index at the moment,
# hence one more step (exactly as git gently suggests):
# (use "git reset HEAD <file>..." to unstage)
git reset
在此之后,您将看到重置后的这些闪亮的未分级更改:并且您的回购处于一种即将提交所有这些文件的状态。从现在起,你可以像往常一样轻松地再次提交。希望这会有所帮助。
gitrebase——交互式可用于将提交拆分为较小的提交。关于rebase的Git文档对这个过程进行了简要的演练-拆分提交:
在交互模式下,您可以使用“编辑”操作标记提交。然而,这并不一定意味着gitrebase希望这次编辑的结果正好是一次提交。实际上,您可以撤消提交,也可以添加其他提交。这可用于将提交分为两部分:使用gitrebase-i<commit>^启动交互式rebase,其中<commit’是要拆分的提交。事实上,任何提交范围都可以,只要它包含该提交。使用“编辑”操作标记要拆分的提交。在编辑提交时,执行git-resetHEAD^。结果是HEAD被重绕了一圈,索引也随之改变。然而,工作树保持不变。现在,将更改添加到第一次提交时所需的索引中。您可以使用gitadd(可能以交互方式)或gitgui(或两者都使用)来实现这一点。使用现在合适的提交消息提交当前索引。重复最后两个步骤,直到工作树干净。使用git-rebase继续rebase--Continue。如果您不能绝对确定中间版本是否一致(编译、通过测试套件等),则应在每次提交、测试和修改提交后使用git stash来隐藏尚未提交的更改。
推荐文章
- 撤消git平分错误
- 使用.gitconfig配置diff工具
- 如何配置Mac OS X术语,使git有颜色?
- Visual Studio Code: .git文件夹/文件隐藏
- “node_modules”文件夹应该包含在git存储库中吗
- 为什么git-rebase给了我合并冲突,而我所做的只是压缩提交?
- 当我试图推到原点时,为什么Git告诉我“没有这样的远程‘原点’”?
- 如何从远程分支中挑选?
- 如何查看一个分支中的哪些提交不在另一个分支中?
- 如何取消在github上的拉请求?
- HEAD和master的区别
- GIT克隆在windows中跨本地文件系统回购
- RPC失败;卷度传输已关闭,剩余未完成的读取数据
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 错误:您对以下文件的本地更改将被签出覆盖