我曾经问过如何压缩git存储库中的前两次提交。

虽然这些解决方案相当有趣,而且不像git中的其他一些东西那样令人费解,但如果您需要在项目开发过程中多次重复这个过程,那么它们仍然是一个众所周知的伤害。

所以,我宁愿只经历一次痛苦,然后能够永远使用标准的交互式rebase。

那么,我想做的是有一个空的初始提交,它的存在仅仅是为了成为第一个。没有代码,什么都没有。只是占地方,这样就可以做地基了。

我的问题是,有了一个现有的存储库,我如何在第一个提交之前插入一个新的空提交,并将其他所有人向前移动?


当前回答

结合最新和最好的。没有副作用,没有冲突,保持标签。

git log --reverse

tree=`git hash-object -wt tree --stdin < /dev/null`
commit=`git commit-tree -m 'Initialize empty repository' $tree`
echo $commit # copy below, interpolation didn't work for me

git filter-branch --parent-filter 'sed "s/^\$/-p <commit>/"' --tag-name-filter cat master

git log --reverse

请注意,在GitHub上,您将丢失CI运行数据和PR可能会搞砸,除非其他分支也得到修复。

其他回答

遵循亚里士多德和其他人的回答,但使用更简单的命令

zsh% git checkout --orphan empty     
Switched to a new branch 'empty'
zsh% git rm --cached -r .
zsh% git clean -fdx
zsh% git commit --allow-empty -m 'initial empty commit'
[empty (root-commit) 64ea894] initial empty commit
zsh% git checkout master
Switched to branch 'master'
zsh% git rebase empty
First, rewinding head to replay your work on top of it...
zsh% git branch -d empty 
Deleted branch empty (was 64ea894).

请注意,您的回购不应该包含任何等待提交的本地修改。 注意git检出——孤儿将在新版本的git中工作,我猜。 注意,大多数时候git状态给出了有用的提示。

我成功地引用了亚里士多德和肯特的回答:

# 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 <sha of newroot>/"' --tag-name-filter cat -- --all
# clean up
# pre- git 2.28...
git checkout master
# or git 2.28 and later...
git checkout $(git config --get init.defaultBranch)
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或init.defaultBranch)。

启动一个新的存储库。

将日期设置为您想要的开始日期。

按照你希望的方式做每件事,调整系统时间以反映你希望那样做的时间。根据需要从现有存储库中提取文件,以避免大量不必要的输入。

当您到达今天时,交换存储库,您就完成了。

如果你只是一个疯狂的(成熟的)但相当聪明的人(很可能,因为你必须有一定的智慧才能想出像这样疯狂的想法),你将编写这个过程。

当你决定让过去的事情从现在开始以另一种方式发生时,这也会让事情变得更好。

结合最新和最好的。没有副作用,没有冲突,保持标签。

git log --reverse

tree=`git hash-object -wt tree --stdin < /dev/null`
commit=`git commit-tree -m 'Initialize empty repository' $tree`
echo $commit # copy below, interpolation didn't work for me

git filter-branch --parent-filter 'sed "s/^\$/-p <commit>/"' --tag-name-filter cat master

git log --reverse

请注意,在GitHub上,您将丢失CI运行数据和PR可能会搞砸,除非其他分支也得到修复。

如果你忘记在"git init"之后立即创建一个空提交,那么在存储库的开始添加一个空提交:

git rebase --root --onto $(git commit-tree -m 'Initial commit (empty)' 4b825dc642cb6eb9a060e54bf8d69288fbee4904)