如何创建一个干净、链接的Git存储库供公众使用?

如何创建一个干净、链接的Git存储库供公众使用?,git,Git,我一直在和一位同事一起整理一些不久前编写的代码。它都在Github存储库(私有)中,有许多分支和提交记录了从一个单一的、难看的、意大利式代码的Python脚本到一个更模块化、可测试的结构的漫长转换 我们现在发现自己需要向外界公开这个较新版本,因为它是我们试图发表的论文的基础。显然,我们可以将存储库公开,但有太多令人尴尬的代码——以及一些意外发生的数据文件,这些文件不允许泄露到组织之外——我们无法做到这一点 我希望能够构建一个只包含代码发布版本的新存储库。我希望在两个回购协议之间保持链接,这样我就

我一直在和一位同事一起整理一些不久前编写的代码。它都在Github存储库(私有)中,有许多分支和提交记录了从一个单一的、难看的、意大利式代码的Python脚本到一个更模块化、可测试的结构的漫长转换

我们现在发现自己需要向外界公开这个较新版本,因为它是我们试图发表的论文的基础。显然,我们可以将存储库公开,但有太多令人尴尬的代码——以及一些意外发生的数据文件,这些文件不允许泄露到组织之外——我们无法做到这一点

我希望能够构建一个只包含代码发布版本的新存储库。我希望在两个回购协议之间保持链接,这样我就可以在代码开发的过程中推动代码的后续版本。有没有一种简单的方法来实现这一点,使得repo1中的历史不会溢出到repo2中

在ASCII艺术形式中,我希望最终得到两份回购协议,如下所示:

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