如何删除除最后五个之外的所有 Git 提交
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11929766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to delete all Git commits except the last five
提问by kayahr
I have a very large Git repository which only contains binary files which are changed pretty often. Naturally the Git repository is muchlarger than the actual files in it. I don't really care about old history, I only need some of the newer history to be able to revert some wrong changes. So let's say I want to remove all commits except the last five.
我有一个非常大的 Git 存储库,它只包含经常更改的二进制文件。当然Git仓库,远高于它的实际文件大。我并不真正关心旧的历史,我只需要一些较新的历史就能恢复一些错误的更改。因此,假设我想删除除最后五个提交之外的所有提交。
Naturally I want to do this to keep the repository small so the removed commits must be purged completely from the repo.
自然地,我想这样做以保持存储库较小,因此必须从存储库中完全清除已删除的提交。
And I want to do all this non-interactively with a single command (alias) or script. How can I do this?
我想使用单个命令(别名)或脚本以非交互方式完成所有这些。我怎样才能做到这一点?
采纳答案by Dan Cruz
Here's an rebase-last-five
alias to get you started. It will recreate the current branch so only the most recent five commits are in the history. It's probably best to make this a script (git-rebase-last-five.sh
) that is available in a directory on your PATH
; Git will find and use scripts named git-....sh
without the need for any special configuration. The script should do more error checking and handling than this simple alias.
这是rebase-last-five
帮助您入门的别名。它将重新创建当前分支,因此历史中只有最近的五个提交。最好将此脚本 ( git-rebase-last-five.sh
) 设置为在您的PATH
;目录中可用。Git 将查找和使用已命名git-....sh
的脚本,无需任何特殊配置。脚本应该比这个简单的别名做更多的错误检查和处理。
$ git config --global alias.rebase-last-five '!b="$(git branch --no-color | cut -c3-)" ; h="$(git rev-parse $b)" ; echo "Current branch: $b $h" ; c="$(git rev-parse $b~4)" ; echo "Recreating $b branch with initial commit $c ..." ; git checkout --orphan new-start $c ; git commit -C $c ; git rebase --onto new-start $c $b ; git branch -d new-start ; git gc'
CAVEAT EMPTOR: Do heed the warnings about changing history.
Check the man
pages (git help <command>
or online) for further information.
检查man
页面(git help <command>
或在线)以获取更多信息。
An example usage:
示例用法:
$ git --version
git version 1.7.12.rc2.16.g034161a
$ git log --all --graph --decorate --oneline
* e4b2337 (HEAD, master) 9
* e508980 8
* 01927dd 7
* 75c0fdb 6
* 20edb42 5
* 1260648 4
* b3d6cc8 3
* 187a0ef 2
* e5d09cf 1
* 07bf1e2 initial
$ git rebase-last-five
Current branch: master e4b2337ef33d446bbb48cbc86b44afc964ba0712
Recreating master branch with initial commit 20edb42a06ae987463016e7f2c08e9df10fd94a0 ...
Switched to a new branch 'new-start'
[new-start (root-commit) 06ed4d5] 5
1 file changed, 1 insertion(+)
create mode 100644 A
First, rewinding head to replay your work on top of it...
Applying: 6
Applying: 7
Applying: 8
Applying: 9
Deleted branch new-start (was 06ed4d5).
Counting objects: 35, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (35/35), done.
Total 35 (delta 4), reused 0 (delta 0)
$ git log --all --graph --decorate --oneline
* a7fb54b (HEAD, master) 9
* 413e5b0 8
* 638a1ae 7
* 9949c28 6
* 06ed4d5 5
回答by amorfis
Ok, if you want what I think you want (see my comment), I think this should work:
好的,如果你想要我认为你想要的(见我的评论),我认为这应该有效:
Create branch to save all the commits (and just in case):
git branch fullhistory
While still on master, reset --hard to the commit you want to retain history from:
git reset --hard HEAD~5
Now reset without
--hard
to the beginning of history, this should leave your workspace untouched, so it remains in HEAD~5 state.git reset --soft <first_commit>
So now you have empty history on
master
, and all the changes you need in the workspace. Just commit them.git commit -m "all the old changes squashed"
Now cherry-pick this 4 commits from
fullhistory
you want to have here:git cherry-pick A..B
创建分支以保存所有提交(以防万一):
git branch fullhistory
仍然在 master 上时,将 --hard 重置为要保留历史记录的提交:
git reset --hard HEAD~5
现在重置而不是
--hard
历史的开始,这应该使您的工作区保持不变,因此它保持在 HEAD~5 状态。git reset --soft <first_commit>
所以现在您在 上有空的历史记录
master
,以及您在工作区中需要的所有更改。只需提交它们。git commit -m "all the old changes squashed"
现在从
fullhistory
你想在这里挑选这 4 个提交:git cherry-pick A..B
Where A is older than B, and remember A is NOT included. So it should be parent of the oldest commit you want to include.
如果 A 比 B 年长,请记住 A 不包括在内。所以它应该是你想要包含的最旧提交的父级。