如果不创建一个分支并在一个新分支上做一堆奇怪的工作,那么在将一个提交提交到本地存储库之后,是否有可能将其分解为几个不同的提交?
当前回答
gitrebase——交互式可用于将提交拆分为较小的提交。关于rebase的Git文档对这个过程进行了简要的演练-拆分提交:
在交互模式下,您可以使用“编辑”操作标记提交。然而,这并不一定意味着gitrebase希望这次编辑的结果正好是一次提交。实际上,您可以撤消提交,也可以添加其他提交。这可用于将提交分为两部分:使用gitrebase-i<commit>^启动交互式rebase,其中<commit’是要拆分的提交。事实上,任何提交范围都可以,只要它包含该提交。使用“编辑”操作标记要拆分的提交。在编辑提交时,执行git-resetHEAD^。结果是HEAD被重绕了一圈,索引也随之改变。然而,工作树保持不变。现在,将更改添加到第一次提交时所需的索引中。您可以使用gitadd(可能以交互方式)或gitgui(或两者都使用)来实现这一点。使用现在合适的提交消息提交当前索引。重复最后两个步骤,直到工作树干净。使用git-rebase继续rebase--Continue。如果您不能绝对确定中间版本是否一致(编译、通过测试套件等),则应在每次提交、测试和修改提交后使用git stash来隐藏尚未提交的更改。
其他回答
之前的回答已经介绍了使用gitrebase-i来编辑要拆分的提交,并将其分部分提交。
当将文件拆分为不同的提交时,这很有效,但如果您想拆分对单个文件的更改,则需要了解更多信息。
使用rebase-i并将其标记为编辑,获得了要拆分的提交,您有两个选项。
使用git reset HEAD~后,使用git add-p逐个检查补丁,以选择每次提交所需的补丁编辑工作副本以删除不需要的更改;承诺该临时状态;然后收回下一轮的全部承诺。
如果要拆分大型提交,选项2很有用,因为它允许您检查临时版本是否作为合并的一部分正确构建和运行。这一过程如下。
使用rebase-i并编辑提交后,使用
git reset --soft HEAD~
撤消提交,但将提交的文件保留在索引中。您也可以通过省略--soft来进行混合重置,这取决于您的初始提交距离最终结果有多近。唯一的区别是您是从所有已暂存更改开始,还是从所有未暂存更改开始。
现在进入并编辑代码。您可以删除更改、删除添加的文件,并执行任何您想要构建的系列的第一次提交的操作。您还可以构建它,运行它,并确认您拥有一组一致的源代码。
一旦您满意,根据需要暂存/取消暂存文件(我喜欢使用gitgui),并通过UI或命令行提交更改
git commit
这是第一次提交。现在,您希望将工作副本恢复到提交后的状态,以便在下次提交时进行更多更改。要查找正在编辑的提交的sha1,请使用gitstatus。在状态的前几行中,您将看到当前正在执行的rebase命令,在其中可以找到原始提交的sha1:
$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
pick 4847406 US135756: add debugging to the file download code
e 65dfb6a US135756: write data and download from remote
(see more in file .git/rebase-merge/done)
...
在本例中,我正在编辑的提交具有sha1 65dfb6a。知道了这一点,我可以使用git checkout的形式在我的工作目录上检查该提交的内容,git checkback同时接受提交和文件位置。这里我用。作为替换整个工作副本的文件位置:
git checkout 65dfb6a .
不要错过最后的点!
这将在您正在编辑的提交后按原样检出和暂存文件,但与您之前提交的文件相比,因此您已经提交的任何更改都不会成为提交的一部分。
您可以现在继续并按原样提交以完成拆分,也可以再次进行,在进行另一次临时提交之前删除提交的某些部分。
如果您想在一次或多次提交中重用原始提交消息,可以直接从rebase的工作文件中使用它:
git commit --file .git/rebase-merge/message
最后,一旦您提交了所有更改,
git rebase --continue
将继续并完成重新启动操作。
从git rebase手册(拆分COMMITS部分)
在交互模式下,您可以使用“编辑”操作标记提交。然而,这并不一定意味着gitrebase希望这次编辑的结果正好是一次提交。实际上,您可以撤消提交,也可以添加其他提交。这可用于将提交分为两部分:使用gitrebase-i<commit>^启动交互式rebase,其中<commit’是要拆分的提交。事实上,任何提交范围都可以,只要它包含该提交。使用“编辑”操作标记要拆分的提交。在编辑提交时,执行git-resetHEAD^。结果是HEAD被重绕了一圈,索引也随之改变。然而,工作树保持不变。现在,将更改添加到第一次提交时所需的索引中。您可以使用gitadd(可能以交互方式)或gitgui(或两者都使用)来实现这一点。使用现在合适的提交消息提交当前索引。重复最后两个步骤,直到工作树干净。使用git-rebase继续rebase--Continue。
在没有交互式重新基础的情况下,最容易做的事情是(可能)在要拆分的分支之前创建一个新的分支,然后在提交、重置、隐藏、提交文件移动、重新应用隐藏并提交更改,然后与前一个分支合并,或者在随后的提交中进行樱桃选择。(然后将以前的分支机构名称改为现在的负责人。)(也许最好遵循MBO的建议,并进行交互式重组。)
现在,在Windows上的最新TortoiseGit中,您可以非常轻松地完成此操作。
打开rebase对话框,对其进行配置,然后执行以下步骤。
右键单击要拆分的提交,然后选择“编辑”(在拾取、挤压、删除…中)。单击“开始”开始重新定基。一旦到达提交拆分,请选中“编辑/拆分”按钮,然后直接点击“修正”。提交对话框打开。取消选择要单独提交的文件。编辑提交消息,然后单击“提交”。在有文件要提交之前,提交对话框将一次又一次打开。当没有更多的文件要提交时,它仍然会询问您是否要再添加一个提交。
非常有用,谢谢TortoiseGit!
如果你有这个:
A - B <- mybranch
如果您在提交B中提交了一些内容:
/modules/a/file1
/modules/a/file2
/modules/b/file3
/modules/b/file4
但是你想把B分解成C-D,得到这样的结果:
A - C - D <-mybranch
例如,您可以这样划分内容(不同提交中来自不同目录的内容)。。。
将分支重置回要拆分的分支之前的提交:
git checkout mybranch
git reset --hard A
创建第一个提交(C):
git checkout B /modules/a
git add -u
git commit -m "content of /modules/a"
创建第二个提交(D):
git checkout B /modules/b
git add -u
git commit -m "content of /modules/b"
推荐文章
- 为什么我需要显式地推一个新分支?
- 如何撤消最后的git添加?
- Rubymine:如何让Git忽略Rubymine创建的.idea文件
- Gitignore二进制文件,没有扩展名
- Git隐藏错误:Git隐藏弹出并最终与合并冲突
- 了解Git和GitHub的基础知识
- 没有。Git目录的Git克隆
- Git与Mercurial仓库的互操作性
- 忽略git中修改(但未提交)的文件?
- “git restore”命令是什么?“git restore”和“git reset”之间有什么区别?
- Git合并与强制覆盖
- Git拉另一个分支
- 在Bash命令提示符上添加git分支
- 如何更改Git日志日期格式
- git pull -rebase和git pull -ff-only之间的区别