仅使用本地存储库历史记录的子集创建GitHub存储库

Set*_*son 44 git fork github

背景:我正在接近开放采购我已经工作了两年多的个人研究代码.它起初是一个SVN存储库,但大约一年前我转移到Git,我想在GitHub上分享代码.然而,多年来它累积了很多,我宁愿公共版本以其现状开始.但是,我仍然愿意为此做出贡献并融入其他人的潜在贡献.

问题是:有没有办法"分叉"一个git存储库,这样就不会在fork(它存在于GitHub上)上保留历史记录,但是我的本地存储库仍然有完整的历史记录,我可以拉/推送到GitHub?

我对大型存储库的管理端没有任何经验,所以非常感谢细节.

Bri*_*ell 70

你可以在Git中轻松创建一个全新的历史.假设您希望您的master分支成为您将推送到GitHub的分支,以及您要存储的完整历史记录old-master.您可以master分支移动到old-master,然后使用以下命令启动没有历史记录的全新分支git checkout --orphan:

git branch -m master old-master
git checkout --orphan master
git commit -m "Import clean version of my code"
Run Code Online (Sandbox Code Playgroud)

现在你有一个master没有历史记录的新分支,你可以推送到GitHub.但是,正如您所说,您希望能够在本地存储库中看到所有旧历史记录; 并且可能希望它不会断开连接.

你可以使用git replace.替换ref是一种在Git查看给定提交时指定备用提交的方法.因此,在查看历史记录时,您可以告诉Git查看旧分支的最后一次提交,而不是新分支的第一次提交.为此,您需要从旧存储库中引入断开连接的历史记录.

git replace master old-master
Run Code Online (Sandbox Code Playgroud)

现在你有了新的分支,在其中你可以看到你的所有历史记录,但是实际的提交对象与旧的历史记录是断开的,所以你可以将新的提交推送到GitHub,而不会出现旧的提交.将您的master分支推送到GitHub,只有新提交将转到GitHub.但采取看看历史gitk或者git log,你会看到完整的历史.

git push github master:master
gitk --all
Run Code Online (Sandbox Code Playgroud)

陷阱

如果你在旧提交上建立任何新的分支,你必须小心保持历史分开; 否则,这些分支上的新提交将在其历史中真正具有旧提交,因此如果将其推送到GitHub,您将完成整个历史记录.master但是,只要您根据新的提交保留所有新提交,就可以了.

如果你曾经跑过git push --tags github,那将推动你的所有标签,包括旧标签,这将导致你的所有旧历史记录随之拉动.你可以通过删除所有旧标签(git tag -d $(git tag -l)),或者从不使用git push --tags但只是手动推送标签,或者使用两个存储库来处理这个问题,如下所述.

这两个问题背后的基本问题是,如果你推送任何连接到任何旧历史的ref(除了通过被替换的提交),你将推高所有旧的历史.避免这种情况的最佳方法可能是使用两个存储库,一个仅包含新提交,另一个包含旧历史和新历史,以便检查完整历史记录.你只需要新的提交就可以完成你所有的工作,你的提交,你从GitHub推送和拉动的回购; 这样,你不可能不小心推动你的旧提交.然后,只要您需要查看整个事物,就可以将所有新提交内容提取到具有完整历史记录的仓库中.您可以从GitHub或其他本地仓库中取出,以更方便的方式.它将是您的存档,但为了避免意外发布您的旧历史记录,您永远不会从它推送到GitHub.以下是如何设置它:

~$ mkdir newrepo
~$ cd newrepo
newrepo$ git init
newrepo$ git pull ~/oldrepo master
# now newrepo has just the new history; we can set up oldrepo to pull from it
newrepo$ cd ~/oldrepo
oldrepo$ git remote add newrepo ~/newrepo
oldrepo$ git remote update
oldrepo$ git branch --set-upstream master newrepo/master
# ... do work in newrepo, commit, push to GitHub, etc.
# Now if we want to look at the full history in oldrepo:
oldrepo$ git pull

如果你的Git早于1.7.2

您没有git checkout --orphan,因此您必须通过从现有存储库的当前版本创建新的存储库,然后提取旧的断开连接的历史记录来手动执行此操作.你可以这样做,例如:

oldrepo$ mkdir ~/newrepo
oldrepo$ cp $(git ls-files) ~/newrepo
oldrepo$ cd ~/newrepo
newrepo$ git init
newrepo$ git add .
newrepo$ git commit -m "Import clean version of my code"
newrepo$ git fetch ~/oldrepo master:old-master

如果你的Git高于1.6.5

git replace1.6.5中添加了替换引用,因此您必须使用较旧的,稍微不那么灵活的称为移植的机制,它允许您为给定的提交指定备用父项.而不是git replace命令,运行:

echo $(git rev-parse master) $(git rev-parse old-master) >> .git/info/grafts
Run Code Online (Sandbox Code Playgroud)

这将使它在本地看起来好像master提交将old-master提交作为其父项,因此您将看到比您更多的提交git replace.