提交git repo的根提交(删除历史记录)

时间:2018-01-12 15:14:10

标签: git

我有一个repo,我试图在很大程度上基于两个可能的代码库之一来实现一个功能。问题是,我一直在工作的git repo实际上是其中一个项目的git repo,但不是我在上面构建我的工作的那个。我当时没有考虑过这个问题,因为我只是在尝试,但现在事实证明我们在这个实验之上已经构建了很多。

在这个新分支的第一次提交中,我删除了所有文件,并粘贴到其他项目的文件中。然后我们建立在这个其他项目的基础上,我们现在大约有100个提交。

我想在第一次分支提交之前删除所有历史记录,我删除了大量文件并添加了大量其他文件,因为历史记录开始有意义。

我该怎么做?

3 个答案:

答案 0 :(得分:1)

一种可能性是使用git rebase来重写您的历史记录。请注意,如果其他人正在处理此代码,这不是一个好习惯,如果您将此代码推送到生产中,则会更加混乱和危险。

无论如何,如果您愿意,可以使用以下命令更改历史记录:

获取要删除的最早提交的提交ID。使用git log查找。

一旦你有了,你可以重写历史:

$ git rebase -i <commitID_A>
pick idZ commit id Z
pick id1 commit id 1
pick id2 commit id 2
...
pick idT commit id T
...
pick id3 commit id 3
pick id4 commit id 4
pick idA commit id A

# Rebase idA onto idZ
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

这就是你要在shell中看到的内容。从这里您可以从帮助日志中看到,您可以决定将选择哪个提交以及哪个提交将被压缩。只需在提交之前更改列表中的单词即可。

注意:如果您这样做,则重写idAHEAD之间的所有提交,所以请确保。

有关详细信息,请查看here

答案 1 :(得分:1)

@rakwaht提到的rebase -i命令确实是重写历史记录的有用工具(通常用于重写由少数尚未推送的提交组成的本地历史记录),但我相信这不是OP用例的最佳工具。

更实际的解决方案是定义一个GraftPoint,其中包含历史记录中您想要的第一个提交的SHA1,并依赖git filter-branch使根提交更改为永久性(此步骤为破坏性操作,所以请确保预先备份您的仓库)

此解决方案已在this question on SO中针对另一个类似的用例提出。

总而言之,你可以这样做(假设你有一个repo文件夹的备份):

git checkout feature
# to checkout the branch of the new project

git log --graph --decorate --pretty=oneline
# to find the first commit to be kept (adding initial files in the new project)

echo 1234567890123456789012345678901234567890 > .git/info/grafts
# to define a GraftPoint with the appropriate SHA1

gitk
# to preview the impact of this GraftPoint

git filter-branch --prune-empty -- HEAD
# to rewrite the history of the current branch, as per the GraftPoint
# --prune-empty is optional and allows one to skip commits with empty content

rm .git/info/grafts
# to remove the GraftPoint and thus restore the other branches

gitk --all
# to inspect all branches
# --> note that the SHA1 of all commits in the feature branch have changed,
# so the new history is incompatible with the old one (w.r.t. merges, etc.)

如果您希望feature分支成为您的仓库中唯一的分支并忘记其他所有分支,您可能需要delete the other branches,然后清除reflog和相应的提交通过运行这些命令(提防:破坏性操作):

git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all
git gc --prune=now --aggressive

比照this part of git-filter-branch's documentation,以及the web site of the BFG repo cleanergit filter-branch的替代品{{1}},可享受更好的效果,并可能在其他用例中有用,可强行重写Git历史记录)

希望这有帮助

答案 2 :(得分:1)

别太辛苦。只需使用现有的树对象创建一个新提交并将其设为 HEAD:

$ h=$( echo 'Initial commit' | git commit-tree HEAD^{tree} )
$ git reset --hard $h > /dev/null