我之前已经问过如何在git存储库中压缩前两个提交.
虽然这些解决方案非常有趣,而且并不像git中的其他一些东西那样令人惊讶,但如果你需要在项目开发过程中多次重复这个过程,它们仍然是一个众所周知的伤害.
所以,我宁愿只经历一次痛苦,然后能够永远使用标准的交互式rebase.
那么,我想做的是拥有一个空的初始提交,仅仅是为了成为第一个提交.没有代码,没有任何东西.只是占用空间,因此它可以作为rebase的基础.
我的问题是,拥有一个现有的存储库,如何在第一个存储库之前插入一个新的空提交,并将其他所有人转移?
创建一个没有副作用的新的完全空提交可能最好直接使用Git的管道.这样做可以避免任何副作用:不接触工作副本或索引,没有临时分支来清理等等.所以:
要创建一个提交,我们需要一个目录树,所以我们先创建一个空的:
tree=`git hash-object -wt tree --stdin < /dev/null`
现在我们可以围绕它进行包装:
commit=`git commit-tree -m 'root commit' $tree`
现在我们可以重申:
git rebase --onto $commit --root master
就是这样.如果你足够了解你的外壳,你可以将整个东西重新排列成一个单行.
(注意:在实践中我现在使用filter-branch
.稍后会编辑它.)
这是同一解决方案的一个更清晰的实现,因为它无需创建额外的存储库,使用遥控器,并纠正一个独立的头部:
# first you need a new empty branch; let's call it `newroot` git checkout --orphan newroot git rm -rf . # then you apply the same steps git commit --allow-empty -m 'root commit' git rebase --onto newroot --root master git branch -d newroot
瞧,你最终master
重写了它的历史,包括一个空根提交.
注意:在没有--orphan
切换到的旧版本的Git 上checkout
,你需要管道创建一个空分支:
git symbolic-ref HEAD refs/heads/newroot git rm --cached -r . git clean -f -d
合并亚里士多德Pagaltzis和Uwe Kleine-König的答案和Richard Bronosky的评论.
git symbolic-ref HEAD refs/heads/newroot git rm --cached -r . git clean -f -d # touch .gitignore && git add .gitignore # if necessary git commit --allow-empty -m 'initial' git rebase --onto newroot --root master git branch -d newroot
(只是把所有东西放在一个地方)
我喜欢亚里士多德的回答.但是发现对于一个大型存储库(> 5000次提交),filter-branch比rebase更好,原因有以下几种:1)它更快2)当出现合并冲突时,它不需要人工干预.3)它可以重写标签 - 保留它们.请注意,filter-branch有效,因为对每个提交的内容没有任何疑问 - 它与此'rebase'之前完全相同.
我的步骤是:
# first you need a new empty branch; let's call it `newroot` git symbolic-ref HEAD refs/heads/newroot git rm --cached -r . git clean -f -d # then you apply the same steps git commit --allow-empty -m 'root commit' # then use filter-branch to rebase everything on newroot git filter-branch --parent-filter 'sed "s/^\$/-p/"' --tag-name-filter cat master
请注意,'--tag-name-filter cat'选项意味着将重写标记以指向新创建的提交.
我成功地使用了亚里士多德和肯特的答案:
# first you need a new empty branch; let's call it `newroot`
git checkout --orphan newroot
git rm -rf .
git commit --allow-empty -m 'root commit'
git filter-branch --parent-filter \
'sed "s/^\$/-p /"' --tag-name-filter cat -- --all
# clean up
git checkout master
git branch -D newroot
# make sure your branches are OK first before this...
git for-each-ref --format="%(refname)" refs/original/ | \
xargs -n 1 git update-ref -d
master
除了标签之外,这还将重写所有分支(不仅仅是).