我有以下提交历史记录:
头部头部~头部~2头部~3
gitcommit--修改当前HEAD提交。但是如何修改HEAD~3?
我有以下提交历史记录:
头部头部~头部~2头部~3
gitcommit--修改当前HEAD提交。但是如何修改HEAD~3?
当前回答
当我需要更深入地修复历史中以前的提交时,我经常使用交互式rebase和--autosquash。它本质上加快了ZelluX的回答所说明的过程,当您需要编辑多个提交时,它特别方便。
根据文档:
--自动撤销当提交日志消息以“squash…“(或”修复…“),并且有一个提交的标题以相同的开头…, 自动修改rebase-i的todo列表,以便标记为挤压的提交在要修改的提交之后立即出现
假设您的历史记录如下:
$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1
并且您有要修改为Commit2的更改,然后使用
$ git commit -m "fixup! Commit2"
或者,您可以使用commit sha而不是commit消息,因此“fixup!e8adec4”或甚至只是commit消息的前缀。
然后在提交之前启动交互式重新基础
$ git rebase e8adec4^ -i --autosquash
编辑器将打开已正确排序的提交
pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3
你只需要保存并退出
其他回答
对我来说,这是为了从回购中删除一些凭证。我试着换基,在换基的过程中遇到了一大堆看似无关的冲突——继续。不要费心尝试重新设置自己的基础,在mac上使用名为BFG(brew-install-BFG)的工具。
嗯,这个解决方案可能听起来很愚蠢,但在某些情况下可以拯救你。
我的一个朋友刚刚无意中提交了一些非常大的文件(四个自动生成的文件,每个文件的大小在3GB到5GB之间),然后在此基础上提交了一些额外的代码,然后才意识到git推送不再有效的问题!
这些文件已在.gitignore中列出,但在重命名容器文件夹后,它们被暴露并提交了!现在,在上面还有几次代码提交,但推送一直在运行(试图上传GB的数据!),最终由于Github的文件大小限制而失败。
交互式rebase或任何类似的问题是,他们会处理这些巨大的文件,并且会花费很长时间来做任何事情。然而,在CLI中花了将近一个小时后,我们不确定文件(和增量)是否真的从历史中删除了,或者只是不包括在当前提交中。推也不起作用,我的朋友真的卡住了。
因此,我提出的解决方案是:
将当前git文件夹重命名为~/Project old。再次从github克隆git文件夹(到~/Project)。签出到同一分支。手动将文件从~/Project旧文件夹cp-r到~/Project。确保不需要签入的大量文件被mved并正确包含在.gitignore中。还要确保您没有用旧文件夹覆盖最近克隆的~/Project中的.git文件夹。这就是有问题的历史记录的所在!现在查看更改。它应该是所有最近提交的联合,不包括有问题的文件。最后提交更改,这很好。
这个解决方案最大的问题是,它处理手动复制一些文件,并且它将所有最近的提交合并为一个(显然使用了一个新的提交哈希)
最大的好处是,它在每一步中都非常清晰,它适用于大型文件(以及敏感文件),并且不会在历史上留下任何痕迹!
更改上次提交:
git commit --amend
// or
git commit --amend -m "an updated commit message"
不修改公共承诺修改后的提交实际上是全新的提交,以前的提交将不再位于当前分支上。
例如,如果您想更改最后三个提交消息或该组中的任何一个提交消息,您可以向git rebase-i提供一个参数,该参数是您要编辑的最后一个提交的父级,即HEAD~2^或HEAD~3。记住~3可能更容易,因为您正在尝试编辑最后三次提交,但请记住,您实际上是在指定四次提交之前,即您要编辑的最后一次提交的父级:
$ git rebase -i HEAD~3
了解更多信息
当我需要更深入地修复历史中以前的提交时,我经常使用交互式rebase和--autosquash。它本质上加快了ZelluX的回答所说明的过程,当您需要编辑多个提交时,它特别方便。
根据文档:
--自动撤销当提交日志消息以“squash…“(或”修复…“),并且有一个提交的标题以相同的开头…, 自动修改rebase-i的todo列表,以便标记为挤压的提交在要修改的提交之后立即出现
假设您的历史记录如下:
$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1
并且您有要修改为Commit2的更改,然后使用
$ git commit -m "fixup! Commit2"
或者,您可以使用commit sha而不是commit消息,因此“fixup!e8adec4”或甚至只是commit消息的前缀。
然后在提交之前启动交互式重新基础
$ git rebase e8adec4^ -i --autosquash
编辑器将打开已正确排序的提交
pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3
你只需要保存并退出
完全非交互式命令(1)
我只是想分享一个我正在使用的别名。它基于非交互式交互式数据库。要将其添加到git中,请运行以下命令(解释如下):
git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'
或者,一个也可以处理未暂存文件的版本(通过先暂存,然后再卸载):
git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'
这个命令的最大优点是它不是vim。
(1) 当然,考虑到重新启动期间没有冲突
用法
git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111
将名称修改为似乎合适IMHO。将流程与--修订:
git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>
解释
git-config—全局别名<名称>'<COMMAND>'-创建名为<NAME>的全局git别名,该别名将执行非git命令<COMMAND>f(){<BODY>};f-一个“匿名”bash函数。SHA=`git rev parse“$1”`;-将参数转换为gitrevision,并将结果赋给变量SHAgitcommit--fixup“$SHA”--fixup提交SHA。参见git提交文档GIT_SEQUENCE_EDITOR=true GIT rebase--交互式--autosquash“$SHA^”gitrebase——交互式“$SHA^”部分已被其他答案覆盖。--autosquash与gitcommit一起使用--fixup,有关更多信息,请参阅gitrebase文档GIT_SEQUENCE_EDITOR=true是使整个事情非交互式的原因。这是我从这篇博客文章中学到的。