压缩我的最后一个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 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
,这比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。 除非你真的需要基于一些提交来自动化一个进程,否则就不那么奇特了。
- 把被压扁的提交放在工作分支上(如果他们还没有的话) – 使用gitk来做这件事
- 查看目标分支(例如“主”)
-
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
提交,包括在内。
注意:结果提交消息按顺序是所有压扁的提交的组合。 如果你不满意,你总是可以通过git commit --amend
来手动修改它。 (或者,编辑别名以符合您的口味。)
如果使用TortoiseGit,则可以将函数Combine to one commit
:
- 打开TortoiseGit上下文菜单
- select
Show Log
- 在日志视图中标记相关的提交
- 从上下文菜单中select
Combine 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
到一个的技术:
-
结帐金回购
git checkout golden_repo_name
-
从它(金回购)创build一个新的分支如下
git checkout -b dev-branch
-
壁球与您已有的本地分支进行合并
git merge --squash feature-branch
-
提交你的改变(这将是开发分支中的唯一提交)
git commit -m "My feature complete"
-
将分支推送到您的本地存储库
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