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

时间:2019-05-22 16:03:56

标签: git

我一直在和一位同事一起整理一些前段时间编写的代码。所有这些都在Github存储库(私有)中,并且有许多分支和提交记录了从一个单一的,丑陋的,意大利面条代码的Python脚本到一个更具模块化,可测试的结构的长期过渡。

我们现在发现自己需要将此更高版本公开给外界,因为它是我们试图发表的论文的基础。显然,我们可以将存储库公开,但是坦白地讲,令人尴尬的代码太多,而且一些偶然提交的数据文件也不允许泄露到组织外部,这使我们能够做到这一点。

我希望能够构建一个仅包含代码发行版本的新存储库。我希望在两个存储库之间保持链接,这样我就可以在开发代码时推送更高版本的代码。是否有一种简单的方法可以实现,以使repo1的历史记录不会溢出到repo2中?

在ASCII艺术形式下,我想得到两个看起来像这样的存储库:

repo1 (private)

A -- B -- C -- D -- H -- I -- J
      \         \
       E ------- F -- G


repo2 (public)

X -- G

使得引用G的repo1和repo2中的分支保持链接。

请注意,AX是不同的,因为私有仓库仅以庞大,丑陋的脚本开始,任何人都不应接触,而公共仓库以README(许可证)开头和一个.gitignore文件。

如果我将repo2称为repo1的远程站点,则可以将指向G的分支推到整个区域,但是它将整个分支一直带回到A,这不是我想要的。我认为我需要将X推入repo1,然后在其中创建一个分支,我可以将G合并并推回去,但是我没有找到任何描述此类操作的内容,我都怀疑在Git图中是否可以表示“未连接”的节点。除了将文件从repo1复制到完全独立的repo2之外,还有什么方法可以实现?

2 个答案:

答案 0 :(得分:1)

查看您的图表

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等),每次您要添加发行版(且仅限 然后)合并(与--no-ff)到该分支。然后,每次更新公共仓库时,请确保仅拉出该分支并限制提取的深度。

(您可能必须为每个发行版包含一个父提交;至少我记得在测试该版本的最后一个版本中这是必要的。否则git不会因为“另一个”父-我有99%的肯定这只是一个工具问题-即数据都已正确存储-但是以前的公共提交-存在,并且提交图也不“看起来正确”。您不包括深度的额外承诺。)

repo1 (private)

A -- B -- C -- D -- H -- I -- J
      \         \              \
       E ------- F              \
                  \              \
                   G ------------ K <--(public)


repo2 (public)

        J
         \
F -- G -- K <--(master)

对于每次更新,您都对本地存储库进行了浅层提取,然后确认您只公开了应该公开的内容-因为每次提取都有可能获取完整的历史记录-确定后,然后将您推送到公共仓库。

答案 1 :(得分:0)

我的建议是创建一个仅包含您要发布的代码的新存储库。此存储库将包含与原始存储库完全相同的文件,但是没有任何历史记录。

然后,要同时管理它们,可以将两个不同的远程添加到本地存储库。这有点奇怪,因为大多数情况下,当您执行此操作时,两个遥控器将共享许多提交,但不必。在这种情况下,它们将完全分开,在根部发散。

但是将这两个远程存储库都添加到本地存储库中的好处是您可以在它们之间cherry-pick进行访问。运行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

然后,当您要进行更新时,请从旧存储库开始,然后cherry-pick过渡到新存储库:

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

现在,您所做的提交(“新功能”)在两个存储库中都存在!