在编写新代码时,我会进行许多小的提交来跟踪我的更改。但是,我的公司更喜欢将每个功能作为单个提交提交。所以解决方案是将我的整个(本地)分支压缩为一个提交。
如何在不使用git rebase --interactive
然后更改pick
为squash
所有提交的情况下压缩整个分支?
在编写新代码时,我会进行许多小的提交来跟踪我的更改。但是,我的公司更喜欢将每个功能作为单个提交提交。所以解决方案是将我的整个(本地)分支压缩为一个提交。
如何在不使用git rebase --interactive
然后更改pick
为squash
所有提交的情况下压缩整个分支?
我首选的方法是双线(不包括下面的步骤 1 和 4)。好处是您不需要知道/记录任何提交 ID,您可以编写一个简单的别名来执行所有涉及的步骤,并且您实际上将整个分支移动到origin /master 以便实际合并到 master 可以很快-forward,不能有任何冲突。
首先,我的假设:
my-feature-branch
. 这个分支已经偏离master
了几个提交;这是签出的分支。master
跟踪远程分支origin/master
my-feature-branch
状态/主状态之上的单个提交(不是您的本地,可能已过时)master
git reset --hard
)我的流程如下:
获取,origin/master
当前也是:
$ git fetch
通过将其重置为指向来丢弃本地分支上的所有提交origin/master
$ git reset --mixed origin/master
将分支先前状态的所有旧更改合并到索引中
$ git merge --squash HEAD@{1}
提交您的更改 - Git 将使用包含来自压缩提交的所有提交消息的提交消息预先填充您的编辑器
我提到的简单别名是:
alias squash="git fetch; git reset --mixed origin/master; git merge --squash HEAD@{1}"
这是一个完美的用例git reset --soft
。
假设你有提交历史
D Your latest patch
C Your second patch
B Your first patch
A Someone else's work
您没有阶段性更改,并且git status
,git log
或git show
告诉您当前处于提交 D。
然后git reset --soft B
将获取提交的累积更改C
并将D
它们暂存以进行提交。git commit --amend
然后会将这些更改“合并”到提交 B 中。
使用如下:
git reset --soft B
git commit --amend
第二个命令将使您的编辑器有机会编辑提交消息。
请注意,如果您在开始此过程之前已暂存更改(即您已完成git add XXX
但未跟进 a git commit
),那么这些暂存更改也将合并到提交中。
可能最好的选择是git merge --squash
在合并时使用。这将使您的分支随着它的开发而离开,这通常更容易进行故障排除,因为您会有一些“我正在更改提交 Z 中的特定功能”的概念,并且查看该特定提交,您拥有所有您对多个文件所做的任何更改的上下文 - 查看作为开发路径压缩结果的单个提交会使您更难记住“哦,是的,我不得不在不同的文件中更改另一件事, 也...”。git bisect
当你有整个路径可用时,你也可以使用它——在被压扁的情况下,它所能告诉你的只是“这个巨大的提交破坏了一些东西”。
使用的结果git merge --squash
是您“合并”到的分支上的单个提交,其中包含来自您的分支的累积更改,但它只留下您的原始分支。
在您开始分支之前找到提交的哈希并将其复制到剪贴板中。然后重置到该哈希。
$ git reset [hash]
然后只需在一条消息中重新添加并重新提交更改。
$ git add -A
$ git commit -m 'EVERYTHING SQUASHED'
编辑您的 git 配置文件~/.gitconfig
并将以下内容添加到别名部分
[alias]
squash = "!f(){ CUR=`git rev-parse HEAD` && git reset --soft ${1} && git commit -m \"$(git log --format=%B ${1}..${CUR})\"; };f"
此别名获取当前 HEAD 提交哈希,重置回您指定的提交,并创建一个新提交,保留所有提交消息。
用法:
git squash <refspec>
refspec 可以是任何有效的提交引用,例如提交哈希、分支名称、标签名称、HEAD^
HEAD~3
最好的办法是进行硬重置并将以前的 HEAD 与壁球合并。这是一个别名:
[alias]
squash = "!f() { git reset --hard $1; git merge --squash HEAD@{1}; git commit; }; f"
这样你就可以这样称呼它:
git squash master
或者从另一个分支挤压,比如dev
:
git squash dev
我认为这不是这个问题的正确答案。
但我通常在使用以下命令向远程上游主服务器发出拉取请求之前压缩我的分支:
git rebase -i master
但是你仍然必须选择要挑选和挤压的东西。