如何创建一个干净、链接的Git存储库供公众使用?
我一直在和一位同事一起整理一些不久前编写的代码。它都在Github存储库(私有)中,有许多分支和提交记录了从一个单一的、难看的、意大利式代码的Python脚本到一个更模块化、可测试的结构的漫长转换 我们现在发现自己需要向外界公开这个较新版本,因为它是我们试图发表的论文的基础。显然,我们可以将存储库公开,但有太多令人尴尬的代码——以及一些意外发生的数据文件,这些文件不允许泄露到组织之外——我们无法做到这一点 我希望能够构建一个只包含代码发布版本的新存储库。我希望在两个回购协议之间保持链接,这样我就可以在代码开发的过程中推动代码的后续版本。有没有一种简单的方法来实现这一点,使得repo1中的历史不会溢出到repo2中 在ASCII艺术形式中,我希望最终得到两份回购协议,如下所示:如何创建一个干净、链接的Git存储库供公众使用?,git,Git,我一直在和一位同事一起整理一些不久前编写的代码。它都在Github存储库(私有)中,有许多分支和提交记录了从一个单一的、难看的、意大利式代码的Python脚本到一个更模块化、可测试的结构的漫长转换 我们现在发现自己需要向外界公开这个较新版本,因为它是我们试图发表的论文的基础。显然,我们可以将存储库公开,但有太多令人尴尬的代码——以及一些意外发生的数据文件,这些文件不允许泄露到组织之外——我们无法做到这一点 我希望能够构建一个只包含代码发布版本的新存储库。我希望在两个回购协议之间保持链接,这样我就
repo1 (private)
A -- B -- C -- D -- H -- I -- J
\ \
E ------- F -- G
repo2 (public)
X -- G
这样repo1和repo2中引用G
的分支保持链接
请注意,A
和X
是不同的,因为私人回购从没有人应该接触到的庞大、丑陋的脚本开始,而公共回购从自述文件、许可证和.gitignore
文件开始
如果我将repo2作为repo1的远程引用,我可以将指向G的分支推过,但它会将整个分支带回到
a
,这不是我想要的。我认为我需要将X
推送到repo1,然后在那里创建一个分支,我可以将G
合并到其中并进行推送,但我还没有找到任何描述这种操作的内容,我怀疑“未连接”节点是否可以在Git图中表示。除了将文件从repo1复制到一个完全独立的repo2之外,还有什么方法可以实现我所需要的吗?查看您的图表
repo1 (private)
A -- B -- C -- D -- H -- I -- J
\ \
E ------- F -- G
repo2 (public)
X -- G
唯一可以是G
的父级的提交是F
,因为提交的标识是包含“谁是我的父级”的提交数据的散列。你可以得到
x -- G'
但是,分支不会以您想要的方式保持链接
一种解决方案是使用浅克隆。差不多
git clone --single-branch master --depth=1
我会给你
(F) -- G
意思是“G
知道F
是它的父项,但是F
和它的历史都不在这个克隆中
保持一个正在运行的历史,而不意外地插入您想要隐藏的深层历史并不是一件小事——所以我真的不推荐这种模式
不过,使其工作的方法是在您的私有回购中创建一个分支(public
或其他东西),并且每次您要向该分支添加一个发布(并且只有在那时)合并(使用--无ff
)时。然后每次更新公共回购时,您都要确保只提取该分支并限制提取深度
(对于每个版本,您可能必须包含一个父提交;至少我记得在我测试这个的上一个版本中,这是必要的。否则git不会发现“另一个”父级(前一个公共提交)存在,并且提交图“看起来不正确”“。我99%确信这只是一个工具问题——即数据都正确存储——但如果不包括一个额外的深度提交,它仍然会使回购更难使用。)
repo1(私有)
A--B--C--D--H--I--J
\ \ \
E---F\
\ \
我的建议是创建一个新的存储库,其中只包含您希望在其中发布的代码。此回购协议将包含与原始回购协议完全相同的文件,但没有任何此类历史记录
然后,为了同时管理它们,您可以向本地存储库添加两个不同的远程设备。这有点奇怪,因为在大多数情况下,当您这样做时,这两个远程设备将共享许多提交,但它们不必这样做。在这种情况下,它们将完全分离,在根部发散
但是,将这两个远程存储库添加到本地存储库的好处是,您可以在它们之间进行选择。运行git log
时,您将看到这两个存储库的历史记录
遵循这个想法可能看起来有点像这样:
# Move into the old repo on your computer
cd old-repo
# Rename the default 'origin' remote name to be 'old'
git remote rename origin old
# Add a new remote repository to your local repository
git remote add new https://github.com/foo/bar
# See the history of both of these repositories
git log --all --oneline --graph --decorate
然后,当您要进行更新时,从旧存储库开始,然后选择新存储库:
git checkout branch-in-old-repo
git add .
git commit -m "New feature"
git push old branch-in-old-repo
# Now checkout a branch on the latest commit of the new repo
git checkout -b branch-in-new-repo new/master
# Cherry-pick the commit you just made into the new repo
git cherry-pick branch-in-old-repo
# Push that cherry-picked commit to the new repository
git push new branch-in-new-repo
现在,您所做的提交(“新功能”)存在于两个存储库中 我只是将merge G压缩到repo2中,然后根据需要用更多的代码重复@Mark Adelsberger在下面解释了一切非常好的事情,本质上git中没有这样的东西(你称之为链接),一切都在你的头脑中。@hidden_4003-我知道链接的事情,但把它挂在我的头脑中有助于我应付:)
git checkout branch-in-old-repo
git add .
git commit -m "New feature"
git push old branch-in-old-repo
# Now checkout a branch on the latest commit of the new repo
git checkout -b branch-in-new-repo new/master
# Cherry-pick the commit you just made into the new repo
git cherry-pick branch-in-old-repo
# Push that cherry-picked commit to the new repository
git push new branch-in-new-repo