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

仅使用本地存储库的子集创建GitHub存储库';历史,git,github,fork,Git,Github,Fork,背景:我正在向我已经工作了两年多的目标迈进。它最初是一个SVN存储库,但大约一年前我搬到了Git,我想在GitHub上分享代码。然而,这些年来,它积累了大量的积垢,我更希望公开版能以目前的状态开始它的生命。然而,我仍然愿意为它做出贡献,并吸收其他人的潜在贡献 问题:有没有一种方法可以“fork”Git存储库,这样就不会在fork(位于GitHub上)上保留任何历史记录,但我的本地存储库仍然有完整的历史记录,并且我可以拉/推到GitHub 我在大型存储库的管理方面没有任何经验,因此非常感谢提供详细

背景:我正在向我已经工作了两年多的目标迈进。它最初是一个SVN存储库,但大约一年前我搬到了Git,我想在GitHub上分享代码。然而,这些年来,它积累了大量的积垢,我更希望公开版能以目前的状态开始它的生命。然而,我仍然愿意为它做出贡献,并吸收其他人的潜在贡献

问题:有没有一种方法可以“fork”Git存储库,这样就不会在fork(位于GitHub上)上保留任何历史记录,但我的本地存储库仍然有完整的历史记录,并且我可以拉/推到GitHub


我在大型存储库的管理方面没有任何经验,因此非常感谢提供详细信息。

您可以很容易地在Git中创建新的、新鲜的历史记录。假设您希望您的
master
分支将被推送到GitHub,并且您的完整历史记录将存储在
old master
中。您可以只使用,然后使用以下命令启动一个没有历史记录的新分支:

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

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

git replace master old-master
cd REPO-B
git remote -v
git remote remove REMOTE_NAME
现在您有了新的分支,在其中您可以看到所有的历史记录,但是实际的提交对象与旧的历史记录断开连接,因此您可以将新的提交推送到GitHub,而不必进行旧的提交。将
master
分支推送到GitHub,只有新的提交才会转到GitHub。但是看看
gitk
git log
中的历史记录,您将看到完整的历史记录

git push github master:master
gitk --all
Gotchas

如果您在旧提交的基础上创建任何新分支,那么您必须小心地将历史记录分开;否则,这些分支上的新提交将在它们的历史记录中真正包含旧的提交,因此如果将其推到GitHub上,您将拉动整个历史记录。不过,只要您根据新的
主控文件
保留所有新提交,您就不会有问题

如果您曾经运行过
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.6.5

git replace
和replace refs是在1.6.5中添加的,因此您必须使用一种较旧的、灵活性稍差的机制,称为,它允许您为给定提交指定备用父级。运行以下命令,而不是git replace命令:

echo $(git rev-parse master) $(git rev-parse old-master) >> .git/info/grafts
这将使它在本地看起来像是
master
commit将
old master
commit作为其父级,因此您将看到比使用
git replace

多一次commit,它似乎是完整的、知识丰富的,但有点复杂

简单的(ier)解决方案是保留两个存储库

您使用的专用GitHub存储库。您可以将所有完整的历史推送到该存储库

git replace master old-master
cd REPO-B
git remote -v
git remote remove REMOTE_NAME

第二个存储库是一个公共GitHub存储库,只有当您想向公众“发布”新版本时,才可以向其发布。您可以使用一个简单的diff+补丁发布到它,然后提交+推送。

一个非常简单而有趣的方法如下所示-

假设您在REPO-A中提交了C1到C10,其中C1是初始提交,C10是最新的头。您想要创建一个新的REPO-B,这样它就可以提交C4到C8(一个子集)

注意:使用此方法将更改提交SHA(例如,在本例中为C4'到C8',但每个提交保留的更改将保持不变,并且您现在的第一次提交将从之前提交的所有更改开始,直到该点合并

我该怎么办?


递归地复制本地计算机上的所有内容

cp -R REPO-A REPO-B
可以选择从REPO-B中删除所有远程设备,因为您很可能希望将其用作单独的存储库

git replace master old-master
cd REPO-B
git remote -v
git remote remove REMOTE_NAME
强制将分支指针移动到子集的后面。对于受试者C4到C8,这将是C8。但最有可能的情况是,您需要直到头部的子集(例如,从C4到C10或C)
git filter-branch
git filter-branch --all
git remote add origin NEWREMOTE
git push -u origin master