2012-08-13 34 views
19

我有一个非常大的Git仓库,其中只包含经常更改的二进制文件。当然,Git存储库是,比其中的实际文件大很多。我并不关心旧的历史,我只需要一些新的历史就能够回复一些错误的变化。假设我想删除除最后五个提交之外的所有提交。如何删除除最后五个之外的所有Git提交

当然,我想这样做是为了让存储库保持较小的状态,以便删除的提交必须从存储库中彻底清除。

我想用单个命令(别名)或脚本非交互式地完成所有这些。我怎样才能做到这一点?

+2

这可能帮助: http://stackoverflow.com/questions/250238/collapsing-a-git-repositorys-history – 2012-08-13 07:33:29

+3

您确定要_remove_所有旧的提交?这意味着也要消除他们的变化。 GIT不会在每次提交中存储“当前状态”,它仅存储更改。你想要做的是将所有旧的提交压缩成一个,不是吗? – amorfis 2012-08-13 09:21:28

回答

8

这里是一个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' 

买者自负:不要听从warnings about changing history

检查man页面(git help <command>online)以获取更多信息。

使用示例:

$ 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 
+3

很棒!谢谢!但不是只使用'git gc',我必须使用'git reflog expire --expire = now --all; git gc --prune = now'实际上使存储库更小。 – kayahr 2012-08-17 15:52:43

+0

@ kayahr很高兴为您提供帮助。感谢您分享实际为您工作的更改。 – 2012-08-17 18:12:16

+0

非常感谢,它的工作原理。你应该在你的答案中将脚本分解成几行。我个人更喜欢在执行外部脚本之前理解我在做什么。 – JulienD 2016-07-14 14:13:31

8

好吧,如果你想要什么,我想你想(见我的意见),我认为这应该工作:

  1. 创建分支保存所有提交(以防万一):

    git branch fullhistory

  2. 虽然仍然在主复位 - 硬到你想从保留历史记录的提交:

    git reset --hard HEAD~5

  3. 现在重置但没有--hard到历史的开始,这应该离开你的工作空间不变,所以它仍然在HEAD〜5状态。

    git reset --soft <first_commit>

  4. 所以,现在你有master空的历史,你在工作区需要各方面的变化。只要提交它们。

    git commit -m "all the old changes squashed"

  5. 现在樱桃采摘从fullhistory这4个提交你想在这里:

    git cherry-pick A..B

其中A比B年纪了,还记得不包括在内。所以它应该是您想要包含的最旧提交的父代。