如何使用Git将我的最后一次X提交压缩成一次提交?
答案 0 :(得分:3176)
如果没有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重新指向您不想压缩的最后一次提交。软复位不会触及索引和工作树,而是将索引保留在新提交的所需状态中(即,它已经具有您将要“扔掉”的提交的所有更改)。
答案 1 :(得分:1661)
使用git rebase -i <after-this-commit>
并使用“squash”或“fixup”替换第二次及后续提交中的“pick”,如the manual中所述。
在此示例中,<after-this-commit>
是SHA1哈希值或当前分支的HEAD的相对位置,从中为rebase命令分析提交。例如,如果用户希望在过去查看当前HEAD的5个提交,则命令为git rebase -i HEAD~5
。
答案 2 :(得分:655)
您可以使用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
documentation for git merge
更详细地介绍了--squash
选项。
更新:此方法相对于Chris Johnsen在his answer中建议的更简单git reset --soft HEAD~12 && git commit
的唯一真正优势是,您可以获得提交消息,其中包含每个提交消息的预先填充你正在挤压。
答案 3 :(得分:182)
我建议尽可能避免使用git reset
- 特别是对于Git-novices。除非你真的需要根据提交的号自动化流程,否则有一种不那么奇特的方式......
git merge --squash (working branch name)
git commit
提交消息将根据壁球预先填充。
答案 4 :(得分:117)
从bash :(或Windows上的Git Bash)添加全局“squash”别名
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
手动修改它。 (或者,编辑别名以符合您的口味。)
答案 5 :(得分:89)
感谢this handy blog post我发现您可以使用此命令来压缩最后3次提交:
git rebase -i HEAD~3
即使您在没有跟踪信息/远程回购的本地分支上,这也很方便。
该命令将打开交互式rebase编辑器,然后允许您按照正常情况重新排序,压缩,重新编写等。
使用交互式rebase编辑器:
交互式rebase编辑器显示最后三次提交。运行命令HEAD~3
时,此约束由git rebase -i HEAD~3
确定。
最新的提交HEAD
首先显示在第1行。以#
开头的行是注释/文档。
显示的文档非常清楚。在任何给定的行上,您可以将命令从pick
更改为您选择的命令。
我更喜欢使用命令fixup
作为这个&#34; squashes&#34;提交更改为上面一行的提交并丢弃提交的消息。
由于第1行的提交为HEAD
,因此在大多数情况下,您将其保留为pick
。
您不能使用squash
或fixup
,因为没有其他提交来压缩提交。
答案 6 :(得分:73)
2020 Simple 解决方案,无需重新设置基准:
git reset --soft HEAD~2
git commit -m "new commit message"
git push -f
2表示将压缩最后两个提交。您可以用任何数字替换它
答案 7 :(得分:53)
如果你使用TortoiseGit,你可以使用函数Combine to one commit
:
答案 8 :(得分:40)
基于this article我发现这个方法对我的用例更容易。
我的'dev'分支超过'origin / dev'提交了96次(所以这些提交还没有被推送到远程)。
我想在推动改变之前将这些提交压缩成一个。我倾向于将分支重置为'origin / dev'状态(这将保留96次提交中的所有更改未分级),然后立即提交更改:
git reset origin/dev
git add --all
git commit -m 'my commit message'
答案 9 :(得分:37)
为此,您可以使用以下git命令。
git rebase -i HEAD~n
n(此处为= 4)是最后一次提交的次数。然后你有以下选项,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
像bellow一样更新,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
有关详情,请点击Link
祝你好运!!答案 10 :(得分:29)
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
shell上使用git。如果您使用不同的操作系统(Windows
或Mac
),那么除编辑器外,上述命令是相同的。你可能会得到不同的编辑。
答案 11 :(得分:27)
Anomies answer很好,但是对此我感到不安全,因此我决定添加一些屏幕截图。
使用git log
查看您的位置。最重要的是,找到您不想想要压扁的第一个提交的提交哈希。所以只有:
在我的情况下,执行git rebase -i [your hash]
$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d
就我而言,我想压缩第一次提交中的所有内容。顺序是从头到尾,与git log
中的顺序完全相反。就我而言,我想要:
如果您只选择了一个提交,而其余的都被压缩,则可以调整一个提交消息:
就是这样。保存此(:wq
)后,就完成了。用git log
来看看。
答案 12 :(得分:25)
如果您位于从Golden Repository(feature-branch
)克隆的远程分支(称为golden_repo_name
)上,那么这是将您的提交压缩为一个的技术:
查看黄金回购
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
答案 13 :(得分:23)
答案 14 :(得分:22)
要在分支上合并提交,请运行:
git rebase -i HEAD~(n number of commits back to review)
示例:
git rebase -i HEAD~1
这将打开文本编辑器,如果您希望将这些提交合并在一起,则必须在每个提交前面将“ pick”切换为“ squash”。来自文档:
例如,如果您希望将所有提交合并为一个,则“ pick”是您进行的第一个提交,所有以后的提交(置于第一个之后)应设置为“ squash”。如果使用vim,请在插入模式下使用:x 保存并退出编辑器。
然后继续进行重新设置:
git rebase --continue
有关此方法以及重写提交历史记录的其他方法的更多信息,请参见this helpful post
答案 15 :(得分:16)
这是超级愚蠢的克鲁迪,但是以一种很酷的方式,所以我只是把它扔进戒指:
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 suggested {。}}。
答案 16 :(得分:15)
真正方便的是:
找到你要压缩的提交哈希,比如d43e15
。
现在使用
git reset d43e15
git commit -am 'new commit name'
答案 17 :(得分:14)
如果您想将每个提交压缩成一次提交(例如,第一次公开发布项目时),请尝试:
git checkout --orphan <new-branch>
git commit
答案 18 :(得分:10)
我认为最简单的方法是通过从master创建一个新分支并进行合并 - 对功能分支进行处理。
git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch
然后,您已准备好提交所有更改。
答案 19 :(得分:8)
要将最后10次提交压缩为1次单次提交:
git reset --soft HEAD~10 && git commit -m "squashed commit"
如果您还想使用压缩的提交来更新远程分支:
git push -f
答案 20 :(得分:7)
int main() {
std::fstream fin("detect_char.txt");
char x;
while (fin >> x) {
if (!isdigit(x)) {
std::cout << "found non-int value = " << x << '\n';
}
}
std::cout << '\n';
return 0;
}
在https://github.com/fleetwood-mac/band-history存储库的这段简短的历史中,您已经打开了一个合并请求,以将Bill Clinton提交合并到原始的{ (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)
)Fleetwood Mac提交中。
您打开了一个拉取请求,并在GitHub上看到了:
四次提交:
认为没有人会愿意阅读完整的存储库历史记录。 (实际上有一个存储库,单击上面的链接!)您决定压缩这些提交。因此,您可以运行MASTER
。然后将其git reset --soft HEAD~4 && git commit
移至GitHub上以清理您的PR。
会发生什么?您刚刚完成了一次从Fritz到Bill Clinton的提交。因为您忘记了昨天您正在从事该项目的白金汉尼克斯版本。而且git push --force
与您在GitHub上看到的不匹配。
git log
git checkout
git reset --soft
,使其直接从起点弯曲到终点答案 21 :(得分:7)
简单的单行代码始终有效,因为您当前在要压扁的分支上,master是它源自的分支,并且最新的commit包含您希望使用的提交消息和作者:
git reset --soft $(git merge-base HEAD master) && git commit --reuse-message=HEAD@{1}
答案 22 :(得分:5)
与这样的工作流程有关的问题的答案如何?
merge --squash
,但团队认为这样做会减慢该过程。)在此页面上没有看到这样的工作流程。 (可能是我的眼睛。)如果我正确理解rebase
,则多次合并将需要多种冲突解决方案。我什至不想考虑!
所以,这似乎对我们有用。
git pull master
git checkout -b new-branch
git checkout -b new-branch-temp
git checkout new-branch
git merge --squash new-branch-temp
//将所有更改置于阶段git commit 'one message to rule them all'
git push
答案 23 :(得分:4)
git rebase -i HEAD^^
其中^的数量是X
(在这种情况下,压缩最后两次提交)
答案 24 :(得分:4)
质疑“最后”的意思可能含糊不清。
例如git log --graph
输出以下(简化):
* commit H0
|
* merge
|\
| * commit B0
| |
| * commit B1
| |
* | commit H1
| |
* | commit H2
|/
|
然后最后提交的时间是H0,合并,B0。要压缩它们,你必须在提交H1上重新绑定你的合并分支。
问题是H0包含H1和H2(通常在合并之前和分支之后提交更多),而B0则不包含。因此,您必须至少管理来自H0,合并,H1,H2,B0的更改。
可以使用rebase但以不同的方式使用其他提到的答案:
rebase -i HEAD~2
这将显示您的选择选项(如其他答案中所述):
pick B1
pick B0
pick H0
将壁球放入H0:
pick B1
pick B0
s H0
保存并退出后,rebase将在H1之后依次应用提交。这意味着它会要求您再次解决冲突(首先HEAD将是H1,然后在应用时累积提交)。
在rebase完成后,您可以选择压缩H0和B0的消息:
* commit squashed H0 and B0
|
* commit B1
|
* commit H1
|
* commit H2
|
P.S。如果你只是重置BO:
(例如,使用此处https://stackoverflow.com/a/18690845/2405850更详细说明的reset --mixed
):
git reset --mixed hash_of_commit_B0
git add .
git commit -m 'some commit message'
然后你压缩到H0,H1,H2的B0变化(在分支之后和合并之前完全没有变更提交。
答案 25 :(得分:4)
我发现更通用的解决方案是不指定N&#39; N&#39;提交,而不是你想要压缩的分支/ commit-id。这比计算提交直到特定提交更不容易出错 - 只需直接指定标记,或者如果你真的想要计数,你可以指定HEAD~N。
在我的工作流程中,我开始了一个分支,我在该分支上的第一次提交总结了目标(即,通常我将推送的内容作为该功能的最终&#39;消息公共存储库。)所以当我完成后,我想要做的就是git squash master
回到第一条消息,然后我就可以推送了。
我使用别名:
squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i
这将在它被删除之前转储被压缩的历史记录 - 如果你想恢复,这会让你有机会通过从控制台获取旧的提交ID来恢复。 (Solaris用户注意到它使用GNU sed -i
选项,Mac和Linux用户应该没问题。)
答案 26 :(得分:3)
除了其他优秀的答案之外,我还想补充git rebase -i
总是让我对提交顺序感到困惑的事情 - 旧版本更新版本更新,反之亦然?这是我的工作流程:
答案 27 :(得分:3)
简单的解决方案:
git reset --soft HEAD~5
git commit -m "commit message"
git push origin branch --force-with-lease
答案 28 :(得分:3)
许多答案都基于 git rebase
命令,但根据我的经验,它对于 git 初学者来说有些复杂和高级。
假设您想压缩最后 3 次提交。然后是以下步骤:
git log -1 --oneline
并记下当前状态的提交 id(以防万一您在 git reset 时做错了)git reset --soft HEAD~3
您将返回 3 次提交(并且有点忘记您之前已经进行了这 3 次提交)git commit -m <NEW_SINGLE_MESSAGE>
即可自动合并您的消息下的三个提交如果 git reset 出现问题,您可以通过 git reset --soft <ORIGINAL_COMMIT>
答案 29 :(得分:3)
如何使用Git将最后的X次提交一起压缩为一次提交?
git rebase -i HEAD~X
将显示以下内容:
pick 1bffc15c My earlier commit
pick 474bf0c2 My recent commit
# ...
对于您要压榨的提交,将 pick 替换为 fixup ,这样它将变为:
pick 1bffc15c My earlier commit
fixup 474bf0c2 My recent commit
# ...
如果它是在vim中打开的(终端中的默认界面),请按键盘上的Esc
,分别输入:wq
和Enter
保存文件。
验证:选中git log
答案 30 :(得分:2)
首先,我找出功能分支与当前主分支之间的提交次数
git checkout master
git rev-list master.. --count
然后,我根据我的功能分支创建另一个分支,保持my-feature
分支不变。
最后,我跑
git checkout my-feature
git checkout -b my-rebased-feature
git checkout master
git checkout my-rebased-feature
git rebase master
git rebase head^x -i
// fixup/pick/rewrite
git push origin my-rebased-feature -f // force, if my-rebased-feature was ever pushed, otherwise no need for -f flag
// make a PR with clean history, delete both my-feature and my-rebased-feature after merge
希望能有所帮助,谢谢。
答案 31 :(得分:2)
答案 32 :(得分:2)
如果您不关心中间提交的提交消息,则可以使用
git reset --mixed <commit-hash-into-which-you-want-to-squash>
git commit -a --amend
答案 33 :(得分:1)
有没有人提到在 IntelliJ IDEA UI 上进行操作是多么容易:
git
窗口Squash Commits
> 编辑压缩的提交消息Force Push
答案 34 :(得分:1)
如果您正在使用GitUp,请选择要与其父级合并的提交,然后按 S 。每次提交都必须执行一次,但它比提出正确的命令行咒语要简单得多。特别是如果它只是偶尔做一次。
答案 35 :(得分:1)
要避免,在重新基于同一分支中的提交时必须解决任何合并冲突,可以使用以下命令
pick
要将所有提交压缩为一个,当系统提示您编辑要合并的提交时(-i标志),请按照其他答案中的建议,将除第一个操作以外的所有操作从squash
更新为recursive
。
在这里,我们使用合并策略(-s标志)ours
和策略选项(-X)git rebase -s ours
,以确保历史记录中的后续提交赢得任何合并冲突。
注意:请勿将此与using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace iMouse
{
public partial class Events : Form
{
public bool TrackerSt;
public FormMouseCR()
{
InitializeComponent();
}
public void ButtonGetCoord_Click(object sender, EventArgs e)
{
Visible = false;
TrackerSt = true;
int x = Cursor.Position.X;
int y = Cursor.Position.Y;
int size = 10; // Arbitrary size
System.Drawing.Graphics graphics = CreateGraphics();
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(x - (size / 2), y - (size / 2), size, size);
graphics.DrawRectangle(System.Drawing.Pens.Red, rectangle);
}
private void FormMouseCR_MouseClick(object sender, MouseEventArgs e)
{
if(TrackerSt){
label1.Text = "X = " + e.X + " ; Y = " + e.Y;
TrackerSt = false;
}
}
private void FormMouseCR_MouseMove(object sender, MouseEventArgs e)
{
if(TrackerSt){
label1.Text = "X = " + e.X + " ; Y = " + e.Y;
}
}
}
}
混淆,后者会做其他事情。
答案 36 :(得分:0)
尝试了此处提到的所有方法。但最后,通过单击此链接,我的问题解决了。 https://gist.github.com/longtimeago/f7055aa4c3bba8a62197
$ git fetch upstream
$ git checkout omgpull
$ git rebase -i upstream/master
< choose squash for all of your commits, except the first one >
< Edit the commit message to make sense, and describe all your changes >
$ git push origin omgpull -f
答案 37 :(得分:0)
1)git reset --soft HEAD〜2 && git commit -m“ 消息”
您需要合并多少个提交,您需要下一个HEAD(例如HEAD〜2)
2)git push
将更改推送到特定分支
答案 38 :(得分:0)
例如,如果您要将所有提交压缩到分支(远程存储库)中的单个提交中,例如:https://bitbucket.org
我所做的是
答案 39 :(得分:0)
只需将此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'
你已经完成了。