我有一个repo,我试图在很大程度上基于两个可能的代码库之一来实现一个功能。问题是,我一直在工作的git repo实际上是其中一个项目的git repo,但不是我在上面构建我的工作的那个。我当时没有考虑过这个问题,因为我只是在尝试,但现在事实证明我们在这个实验之上已经构建了很多。
在这个新分支的第一次提交中,我删除了所有文件,并粘贴到其他项目的文件中。然后我们建立在这个其他项目的基础上,我们现在大约有100个提交。
我想在第一次分支提交之前删除所有历史记录,我删除了大量文件并添加了大量其他文件,因为历史记录开始有意义。
我该怎么做?
答案 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中看到的内容。从这里您可以从帮助日志中看到,您可以决定将选择哪个提交以及哪个提交将被压缩。只需在提交之前更改列表中的单词即可。
注意:如果您这样做,则重写idA
和HEAD
之间的所有提交,所以请确保。
有关详细信息,请查看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 cleaner(git filter-branch
的替代品{{1}},可享受更好的效果,并可能在其他用例中有用,可强行重写Git历史记录)
希望这有帮助
答案 2 :(得分:1)
别太辛苦。只需使用现有的树对象创建一个新提交并将其设为 HEAD:
$ h=$( echo 'Initial commit' | git commit-tree HEAD^{tree} )
$ git reset --hard $h > /dev/null