使用Git将我的最后一次X提交压缩

如何使用Git将我最后的X提交压缩成一个提交?     
已邀请:
如手册中所述,使用
git rebase -i <after-this-commit>
并在第二次及后续提交中用“壁球”或“修正”替换“选择”。 在此示例中,
<after-this-commit>
是SHA1哈希值或当前分支的HEAD的相对位置,从中为rebase命令分析提交。例如,如果用户希望在过去查看当前HEAD的5次提交,则命令为
git rebase -i HEAD~5
。     
没有
git rebase
git merge --squash
,你可以相当容易地做到这一点。在这个例子中,我们将压缩最后3次提交。 如果要从头开始编写新的提交消息,这就足够了:
git reset --soft HEAD~3 &&
git commit
如果你想用现有提交消息的串联开始编辑新的提交消息(即类似于pick / squash / squash / ... /squash
git rebase -i
指令列表将启动你),那么你需要提取这些消息和将它们传递给
git commit
git reset --soft HEAD~3 && 
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
这两种方法都以相同的方式将最后三次提交压缩成一个新的提交。软复位只是将HEAD重新指向您不想压缩的最后一次提交。软复位不会触及索引和工作树,使索引处于新提交所需的状态(即,它已经具有您即将“扔掉”的提交的所有更改)。     
你可以使用
git merge --squash
,这比ѭ6更优雅。假设您是主人,并且您希望将最后12次提交压缩为一次。 警告:首先确保你的工作检查
git status
是干净的(因为
git reset --hard
将丢弃分阶段和未分阶段的更改) 然后:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12

# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}

# Commit those squashed changes.  The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
git merge
的文档更详细地描述了
--squash
选项。 更新:克里斯·约翰森(Chris Johnsen)在他的回答中建议的这种方法唯一真正优于简单的
git reset --soft HEAD~12 && git commit
,你得到的提交信息预填充了你正在压缩的每个提交消息。     
我建议尽可能避免使用
git reset
- 特别是对于Git-novices。除非你真的需要基于一些提交自动化一个进程,否则有一种不那么奇特的方式...... 将待压缩的提交放在工作分支上(如果它们还没有) - 请使用gitk 检查目标分支(例如'master')
git merge --squash (working branch name)
git commit
提交消息将根据壁球预先填充。     
根据Chris Johnsen的回答, 从bash添加全局“squash”别名:(或Windows上的Git Bash)
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
...或使用Windows的命令提示符:
git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f"
你的
~/.gitconfig
现在应该包含这个别名:
[alias]
    squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f"
用法:
git squash N
...自动压缩最后的
N
提交,包括在内。 注意:结果提交消息是所有压缩提交的组合,按顺序。如果您对此不满意,您可以随时手动修改它。 (或者,编辑别名以符合您的口味。)     
感谢这篇方便的博客文章,我发现你可以使用这个命令来压缩最后3次提交:
git rebase -i HEAD~3
这很方便,因为即使您在没有跟踪信息/远程仓库的本地分支上也能正常工作。 该命令将打开交互式rebase编辑器,然后允许您按正常方式重新排序,压缩,重写等。 使用交互式rebase编辑器: 交互式rebase编辑器显示最后三次提交。运行命令
git rebase -i HEAD~3
时,此约束由
HEAD~3
确定。 最新的提交,
HEAD
,首先显示在第1行。以
#
开头的行是注释/文档。 显示的文档非常清楚。在任何给定的行上,您可以将命令从
pick
更改为您选择的命令。 我更喜欢使用命令
fixup
,因为这会将提交的更改“压缩”到上面一行的提交中,并丢弃提交的消息。 由于第1行的提交是
HEAD
,在大多数情况下,你将其保留为
pick
。  你不能使用
squash
fixup
,因为没有其他提交来压缩提交。     
如果你使用TortoiseGit,你可以使用
Combine to one commit
的功能: 打开TortoiseGit上下文菜单 选择
Show Log
在日志视图中标记相关提交 从上下文菜单中选择
Combine to one commit
此函数自动执行所有必需的单个git步骤。 不幸的是只适用于Windows。     
基于这篇文章,我发现这个方法对我的用例更容易。 我的'dev'分支在96个提交之前超过了'origin / dev'(所以这些提交还没有推到远程)。 我想在推动改变之前将这些提交压缩成一个。我倾向于将分支重置为'origin / dev'状态(这将保留96个提交中的所有更改未分级),然后立即提交更改:
git reset origin/dev
git add --all
git commit -m 'my commit message'
    
为此,您可以使用以下git命令。
 git rebase -i HEAD~n
n(此处为4)是最后一次提交的次数。然后你有以下选择,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
更新如下,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
有关详细信息,请单击链接 祝好运!!     
1)识别提交短哈希
# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....
这里甚至
git log --oneline
也可用于获得短哈希。 2)如果你想压缩(合并)最后两次提交
# git rebase -i deab3412 
3)这打开了一个用于合并的
nano
编辑器。它看起来像下面
....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....
4)将
pick
重命名为
squash
,它出现在
abcd1234
之前。重命名后应该如下所示。
....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....
5)现在保存并关闭
nano
编辑器。按
ctrl + o
并按
Enter
保存。然后按
ctrl + x
退出编辑器。 6)然后
nano
编辑器再次打开以更新注释,如有必要,请更新它。 7)现在它成功压扁,您可以通过检查日志来验证它。
# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....
8)现在推动回购。注意在分支名称前添加
+
符号。这意味着强制推动。
# git push origin +master
注意:这是基于在
ubuntu
hell上使用git。如果您使用不同的操作系统(
Windows
Mac
),则除编辑器外,上述命令相同。你可能得到不同的编辑器。     
如果您位于从Golden Repository(
golden_repo_name
)克隆的远程分支(称为
feature-branch
),那么这是将您的提交压缩为一个的技术: 查看黄金回购
git checkout golden_repo_name
从中创建一个新分支(黄金回购),如下所示
git checkout -b dev-branch
壁球与您已经拥有的当地分支合并
git merge --squash feature-branch
提交你的更改(这将是dev-branch中唯一的提交)
git commit -m "My feature complete"
将分支推送到本地存储库
git push origin dev-branch
    
Anomies答案很好,但我对此感到不安全,所以我决定添加一些屏幕截图。 第0步:git log 查看
git log
的位置。最重要的是,找到你不想压缩的第一次提交的提交哈希。所以只有: 第1步:git rebase 在我的情况下执行
git rebase -i [your hash]
$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d
第2步:挑选/挤压你想要的东西 在我的情况下,我想在第一次提交的时候压缩所有内容。排序从头到尾,完全与
git log
相反。在我的情况下,我想: 第3步:调整消息 如果您只选择了一个提交并压缩其余提交,则可以调整一个提交消息: 而已。一旦你保存了这个(
:wq
),你就完成了。看看
git log
吧。     
在分支中,您想要组合提交,运行:
git rebase -i HEAD~(n number of commits back to review)
这将打开文本编辑器,如果您希望将这些提交合并在一起,则必须使用'squash'切换每个提交前面的'pick'。例如,如果您要将所有提交合并为一个,那么'pick'是您做的第一个提交,所有未来的提交(放在第一个提交之下)应设置为'squash'。如果使用vim,请在插入模式下使用:x来保存并退出编辑器。 然后继续改变:
git rebase --continue
有关此方法和其他重写提交历史记录的更多信息,请参阅此有用的帖子     
这是超级愚蠢的kludgy,但是以一种很酷的方式,所以我只是把它扔进戒指:
GIT_EDITOR='f() { if [ "$(basename $1)" = "git-rebase-todo" ]; then sed -i "2,$s/pick/squash/" $1; else vim $1; fi }; f' git rebase -i foo~5 foo
翻译:为git提供一个新的“编辑器”,如果要编辑的文件名是
git-rebase-todo
(交互式rebase提示),除了第一个“选择”改为“壁球”,否则会产生vim - 所以当你是提示编辑压缩的提交消息,你得到vim。 (显然我在分支foo上压缩了最后五次提交,但是你可以随意更改它。) 不过,我可能会做马克·朗格尔所建议的。     
如果您想将每个提交压缩到一个提交中(例如,在第一次公开发布项目时),请尝试:
git checkout --orphan <new-branch>
git commit
    
什么可以真正方便: 找到你要压缩的提交哈希,比如说
d43e15
。 现在用
git reset d43e15
git commit -am 'new commit name'
    
我认为最简单的方法是通过从master创建一个新的分支并进行合并 - 对功能分支进行处理。
git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch
然后,您已准备好提交所有更改。     
将最后10次提交压缩为1次提交:
git reset --soft HEAD~10 && git commit -m "squashed commit"
如果您还想使用压缩提交更新远程分支:
git push -f
    
⚠️警告:“我的最后一次X提交”可能含糊不清。
  (MASTER)  
Fleetwood Mac            Fritz
      ║                    ║
  Add Danny  Lindsey     Stevie       
    Kirwan  Buckingham    Nicks                                              
      ║         ╚═══╦══════╝     
Add Christine       ║          
   Perfect      Buckingham
      ║           Nicks            
    LA1974══════════╝                                    
      ║                  
      ║                  
    Bill <══════ YOU ARE EDITING HERE
  Clinton        (CHECKED OUT, CURRENT WORKING DIRECTORY)              
在https://github.com/fleetwood-mac/band-history存储库的这个非常简短的历史记录中,您已经打开了一个拉取请求,将Bill Clinton提交合并到最初的(
MASTER
)Fleetwood Mac提交中。 你打开了拉取请求,在GitHub上你看到了这个: 四个提交: 添加Danny Kirwan 添加Christine Perfect LA1974 比尔·克林顿 认为没有人会关心阅读完整的存储库历史记录。 (实际上有一个存储库,单击上面的链接!)您决定压缩这些提交。所以你去运行
git reset --soft HEAD~4 && git commit
。然后你把它onto91到GitHub来清理你的公关。 会发生什么?你刚刚从弗里茨到比尔克林顿做了一次提交。因为你昨天忘记了你正在研究这个项目的Buckingham Nicks版本。并且
git log
与你在GitHub上看到的不一致。

要回复问题请先登录注册