我用:
git checkout -b testbranch
我做了20次提交。
现在我想要压缩这20个提交。我是这样做的:
git rebase -i HEAD~20
如果我不知道有多少次提交呢?有没有什么方法可以做到:
git rebase -i all on this branch
我用:
git checkout -b testbranch
我做了20次提交。
现在我想要压缩这20个提交。我是这样做的:
git rebase -i HEAD~20
如果我不知道有多少次提交呢?有没有什么方法可以做到:
git rebase -i all on this branch
当前回答
How
你需要得到分支的合并基
git merge-base master your-branch
# 566f8438e0cd0e331ceb49a9cb0920143dfb065c
然后你就可以改基了
git rebase -i 566f8438e0cd0e331ceb49a9cb0920143dfb065c
# then squash/pick/do commit messages
或者只是进行软重置并提交所有内容
git reset --soft 566f8438e0cd0e331ceb49a9cb0920143dfb065c
git add .
git commit -m "The only commit"
自动化
如果你经常这样做,你可以把这些放在你的.bashrc使用自动化。
g-rebase-branch() {
git branch --show-current | xargs git merge-base master | xargs git rebase -i
}
g-one-commit() {
local last_commit_message=`git show -s --format=%s`
git branch --show-current | xargs git merge-base master | xargs git reset --soft
git add -A
git commit -m "$last_commit_message"
git commit --amend
}
然后直接在终端上做这些。
g-one-commit
但如果你合并的是与master不同的分支,那么你可以用“$1”替换master来做到这一点
g-one-commit staging
其他回答
另一种简单的方法是:在原始分支上进行合并-挤压。该命令不执行“压缩”提交。当你这样做时,你分支的所有提交消息将被收集。
$ git checkout master
$ git merge --squash yourBranch
$ git commit # all commit messages of yourBranch in one, really useful
> [status 5007e77] Squashed commit of the following: ...
为了完善一下Caveman的回答,使用git reset——soft <commit>。从文档中,这个命令:
根本不触及索引文件或工作树(但将头部重置为<commit>,就像所有模式一样)。这将使所有更改过的文件都变成“要提交的更改”,就像git状态所显示的那样。
换句话说,它将撤销到<commit>之前的所有提交。但是它不会改变工作目录。您最终会得到所有的更改,这些更改都是未分期和未提交的。就好像那些介入的提交从未发生过一样。
例子:
# on master
git checkout -b testbranch
# make many commits
git reset --soft master
git add .
git commit -m 'The only commit.'
此时,您仍然在testbranch上,它只有一次提交。像往常一样合并到master中。
在我的手中,Caveman回答的第一部分(git rebase -i)并没有压缩提交。
我知道这个问题已经有了答案,但我围绕已接受的答案编写了一个bash函数,以允许您在一个命令中完成它。它首先创建一个备份分支,以防压缩由于某种原因失败。然后压缩并提交。
# Squashes every commit starting after the given head of the given branch.
# When the squash is done, it will prompt you to commit the squash.
# The head of the given parent branch must be a commit that actually exists
# in the current branch.
#
# This will create a backup of the current branch before it performs the squash.
# The name of the backup is the second argument to this function.
#
# Example: $ git-squash master my-current-branch-backup
git-squash() {
PARENT_BRANCH=$1
BACKUP_BRANCH=$2
CURRENT_BRANCH=$(git branch --show-current)
git branch $BACKUP_BRANCH
BACKUP_SUCCESS=$?
if [ $BACKUP_SUCCESS -eq 0 ]; then
git reset $(git merge-base $PARENT_BRANCH $CURRENT_BRANCH)
git add -A
git commit
echo "Squashed $CURRENT_BRANCH. Backup of original created at $BACKUP_BRANCH$"
else
echo "Could not create backup branch. Aborting squash"
fi
}
另一种压缩所有提交的方法是将索引重置为master:
git checkout yourBranch
git reset $(git merge-base master $(git branch --show-current))
git add -A
git commit -m "one commit on yourBranch"
这并不完美,因为这意味着你知道“你的分支”来自哪个分支。 注意:在Git中找到原始分支并不容易/不可能(可视化的方式通常是最简单的,如图所示)。
注意:git分支——show-current已在git 2.22(2019年第二季度)中引入。
或者,正如Hiroki Osame在评论中指出的那样:
git switch yourBranch
git reset --soft $(git merge-base main HEAD)
git commit -m "one commit on yourBranch"
不需要git分支——show-current,因为HEAD已经是该分支的引用。 不需要git add -A,因为git重置-soft只移动HEAD,并保持索引不变(换句话说,文件已经“添加”)。
编辑:你将需要使用git push——force
Karlotcha Hoa在评论中写道:
对于重置,可以这样做 git reset $(git merge-base master $(git rev-parse——abbrev-ref HEAD)) 自动使用您当前所在的分支。 如果使用它,还可以使用别名,因为该命令不依赖于分支名称。
Sschoof在评论中补充道:
因为我的默认分支被称为main,我的搜索多次把我带到这里: 为我下次上课抄一份 git reset $(git merge-base main $(git rev-parse——abbrev-ref HEAD))
假设你在特征分支上:
在特性分支中找到第一个提交。如果你正在使用gitlab或github,你可以直接在分支中查看它,并从那里复制散列,或者你可以使用以下命令:
Git日志<source_branch>..< feature_branch >——漂亮=格式:% h
执行以下命令:
git reset --soft <base_commit_hash>
git commit --amend --no-edit
现在在这个阶段,在您的本地,您有一个提交,其中包括在所有以前的提交中所做的更改。
回顾它,你需要用力推它。在强制推送之后,所有的更改都将合并到一个提交中,而您的分支将只有1个提交。
在特征分支中强制推送
git push --force