压缩我的最后一个X使用Git一起提交

我怎样才能用Git把我最后一次提交的X提交到一个提交中?

使用git rebase -i <after-this-commit>并按照手册中的描述,用“squash”或“fixup”replace第二个和后续提交中的“pick”。

在这个例子中, <after-this-commit>是SHA1哈希值或当前分支的HEAD的相对位置,从这个分支中分析提交的rebase命令。 例如,如果用户希望查看来自当前HEAD的5次提交,那么该命令是git rebase -i HEAD~5

你可以很容易地做到这一点,没有git rebasegit 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 ,这比git rebase -i稍微优雅。 假设你是主人,你想把最后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选项。


更新:这个方法在简单的git reset --soft HEAD~12 && git commit的唯一真正的优势 – Chris Johnsen在他的回答中build议的git reset --soft HEAD~12 && git commit是你用每一个你正在git reset --soft HEAD~12 && git commit的提交消息预先填充提交消息。

我build议在可能的时候避免git reset ,特别是对于Git-novices。 除非你真的需要基于一些提交来自动化一个进程,否则就不那么奇特了。

  1. 把被压扁的提交放在工作分支上(如果他们还没有的话) – 使用gitk来做这件事
  2. 查看目标分支(例如“主”)
  3. git merge --squash (working branch name)
  4. 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提交,包括在内。

注意:结果提交消息按顺序是所有压扁的提交的组合。 如果你不满意,你总是可以通过git commit --amend来手动修改它。 (或者,编辑别名以符合您的口味。)

如果使用TortoiseGit,则可以将函数Combine to one commit

  1. 打开TortoiseGit上下文菜单
  2. selectShow Log
  3. 在日志视图中标记相关的提交
  4. 从上下文菜单中selectCombine to one commit

合并提交

这个函数自动执行所有必要的单个git步骤。 不幸的是只能用于Windows。

感谢这个方便的博客文章,我发现你可以使用这个命令来压缩最后3个提交:

 git rebase -i HEAD~3 

即使在没有跟踪信息/远程回购的本地分支上,它也能正常工作。

该命令将打开交互式底线编辑器,然后允许您重新sorting,压扁,reword,等等正常。

基于这篇文章,我发现这个方法更容易为我的用例。

我的'dev'分支在96次提交之前就是'origin / dev'(所以这些提交并没有推送到远程)。

在推动变革之前,我想压缩这些提交。 我优先考虑将分支重置为“origin / dev”状态(这将使96次提交的所有更改都不进行),然后立即提交更改:

 git reset origin/dev git add --all git commit -m 'my commit message' 

如果您位于从Golden Repository( golden_repo_name )克隆的远程分支(称为feature-branch ),那么以下是将提交golden_repo_name到一个的技术:

  1. 结帐金回购

     git checkout golden_repo_name 
  2. 从它(金回购)创build一个新的分支如下

     git checkout -b dev-branch 
  3. 壁球与您已有的本地分支进行合并

     git merge --squash feature-branch 
  4. 提交你的改变(这将是开发分支中的唯一提交)

     git commit -m "My feature complete" 
  5. 将分支推送到您的本地存储库

     git push origin dev-branch 

要做到这一点,你可以使用下面的git命令。

  git rebase -i HEAD~n 

n(= 4这里)是最后一次提交的次数。 然后你有以下的select,

 pick 01d1124 Message.... pick 6340aaa Message.... pick ebfd367 Message.... pick 30e0ccb Message.... 

像波纹pipe一样更新,

 p 01d1124 Message.... s 6340aaa Message.... s ebfd367 Message.... s 30e0ccb Message.... 

有关详情,请单击链接

祝你好运!!

这是一个非常酷的方式,但以一种很酷的方式,所以我只是把它扔进戒指:

 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提示符),除了第一个“pick”到“squash”之外,都会改变,否则会产生vim -当你被提示编辑压扁的提交信息时,你会得到vim。 (显然,我正在压制分支foo上的最后五个提交,但是你可以改变,但是你喜欢。)

不过我可能会做Mark Longair的build议 。

如果你想压缩每一个提交到一个单一的提交(例如,当第一次公开发布项目),请尝试:

 git checkout --orphan <new-branch> git commit 

我发现更通用的解决scheme不是指定'N'的提交,而是你想要压扁的分支/提交ID。 这比计算提交直到特定提交的错误更less – 只需直接指定标记,或者如果您确实要计数,则可以指定HEAD〜N。

在我的工作stream程中,我开始了一个分支,我在该分支上的第一个提交总结了目标(即通常我将推送为公共存储库的“最终”消息)。我想要做的是git squash master回到第一个消息,然后我准备推。

我使用别名:

 squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i 

这会在转储之前转储历史logging – 如果要还原,这将使您有机会通过从控制台获取旧的落实ID来进行恢复。 (Solaris用户注意到它使用GNU sed -i选项,Mac和Linux用户应该没问题。)

看看这个要点:

Gist – 容易的git南瓜

你必须input例如git-squash 3就是这样。 最后三个提交合并成一个连接他们的消息。

有问题的话,可能会含糊不清“最后”的含义。

例如git log --graph输出以下(简化):

 * commit H0 | * merge |\ | * commit B0 | | | * commit B1 | | * | commit H1 | | * | commit H2 |/ | 

然后按时间最后提交是H0,合并,B0。 为了挤压它们,你必须在提交H1时重新绑定你的合并分支。

问题是H0包含H1和H2(并且通常在合并之前和分支之后提交更多),而B0则不提供。 所以你必须至less从H0pipe理变化,合并H1,H2,B0。

有可能使用rebase,但以不同的方式,然后在其他人提到的答案:

rebase -i HEAD~2

这将显示您的select选项(如其他答案中所述):

 pick B1 pick B0 pick H0 

把南瓜,而不是selectH0:

 pick B1 pick B0 s H0 

保存并退出后,在H1之后轮stream应用提交。 这意味着它会要求你再次解决冲突(HEAD首先是H1,然后在应用时累积提交)。

rebase完成后你可以select压扁的H0和B0:

 * commit squashed H0 and B0 | * commit B1 | * commit H1 | * commit H2 | 

PS如果你只是做一些复位BO:(例如,使用reset --mixed ,在这里更详细地解释https://stackoverflow.com/a/18690845/2405850 ):

 git reset --mixed hash_of_commit_B0 git add . git commit -m 'some commit message' 

然后你压缩成H0,H1,H2的B0变化(在分支之后和合并之前完全失败了。

什么可以很方便:find你想压扁的提交哈希顶部; 说这是现在使用

git reset d43e15

git commit -am 'new commit name'

如果您正在使用GitUp ,请select您要与其父级合并的提交,然后按S键。 每次提交都必须执行一次,但要比提出正确的命令行咒语要简单得多。 特别是如果这是你偶尔做的事情。

只需将这个bash函数添加到.zshrc文件的bash中。

 # Squash last X commits with a Commit message. # Usage: squash X 'COMMIT_MSG' # where X= Number of last commits. # where COMMIT_MSG= New commit msg. function squash() { if [ -z "${1}" -o -z "${2}" ]; then echo "Usage: \`squash X COMMIT_MSG\`" echo "X= Number of last commits." echo "COMMIT_MSG= New commit msg." return 1 fi git reset --soft HEAD~"$1" git add . && git ci -m "$2" # With 100 emoji git push --force } 

然后就跑吧

 squash X 'New Commit Message' 

你完成了。

这个命令为我的工作起到了作用git rebase -i HEAD~<no. of commits you want to squash> git rebase -i HEAD~<no. of commits you want to squash>

你也想在压扁之前检查一下git log以得到实际的no。 承诺被压扁!

切换到主分支,并确保您是最新的:

sh git checkout master && git fetch && git pull

将您的function分支合并到本地主分支中:

sh git merge feature_branch

重置本地主分支到原点状态:

sh git reset origin/master

现在所有的更改都被认为是已更改。 您可以将它们提交并提交到一个或多个提交中。

sh git add . --all git commit