仅将git存储库的一部分公开为公共克隆,但具有完整历史记录

时间:2014-09-02 16:54:46

标签: git svn github version-control

我们在SVN中有代码,但现在切换到Git。

问题是我们有这个文件夹:

/src/com/something/main
/src/com/something/dev

,Eclipse源文件夹设置为/src

只有包.../main中的代码必须公开。

.../dev中的代码未完成并且是私有的。

.../dev中的代码完成后,我们将类移到Eclipse中的.../main。这是一个不同的Java包,我们不使用分支。所以这不是合并。

我试过

git filter-branch --index-filter
'git rm --cached --ignore-unmatch src/com/something/dev'

然而,移动前的所有历史都丢失了,文件突然出现了由移动的作者完成!

如何将存储库拆分为两个分支:分支“secret”包含所有内容,分支“public”具有文件夹.../main中所有文件的完整历史记录,即使文件最初位于文件夹.../dev中也是如此被隐藏了吗?

假设文件历史记录如下

.../dev/file1 created    moved to .../main/file1 (released)
.../dev/file2 created    but not released

然后我需要公开版本来显示两个提交:.../dev/file1的创建和移动到发布。当然,在此文件之间进行的任何编辑。 .../dev/file2的存在/历史应该只在完整的存储库中。更糟糕的是:某些提交修改file1file2,但只发布了file1

git是否允许这样做?有一个“秘密”分支,但是当将文件从秘密分支推送到主分支时,所有历史记录也会被移动?或者它是否提交最终文件(没有历史记录)来发布分支?文件重命名似乎也非常糟糕。它如何处理未推送的相同提交中的其他文件?是否有一个git命令将file1提交到仅包含此文件的所有历史记录的“public”,而不是同一提交中的其他文件?

1 个答案:

答案 0 :(得分:0)

简短回答是git mv dev /src/com/something/dev /src/com/something/main。这保留了历史。但是你不想保留所有的历史,你想要一个不同的历史。因此,您必须将涉及未发布文件的提交的公共和私有部分分开。并且git需要知道移动(来自git mv或因为它自动检测重定位)以便有机会将旧文件的历史与新路径相关联。即使该历史被修改。

所以一个开始的问题可能是"什么是触及/ src / com / something / dev和/ src / com / something / main的提交的交集?"

git log --reverse --pretty=oneline /src/com/something/main /src/com/something/dev >combined_commits.log
git log --pretty=oneline /src/com/something/dev  >dev_commits.log
git log --pretty=oneline /src/com/something/main >main_commits.log
sort main_commits.log dev_commits.log | uniq -d  >bad_history.log

因此,最终列表具有触及两者的所有提交(但不是原始提交,即combined_commits.log命令)。没有一个命令可以执行您想要的操作,但您可以编写脚本。松散的算法是:

git rebase -i $ {EARLIEST_CONFLICT_HASH} ~1

马克"编辑"对于所有糟糕的提交,例如:

...
pick c6d108f Auto-detect catkey vs. barcode
pick 8616c0e Directory cleanup
edit ae885c6 Move registration url to '/register'
pick af5394f Initiate workflow on registration
...

保存/退出。然后在每个"编辑"相:

git commit /src/*/*/dev  # commit dev stuff separately first
git add /src/*/*/main    
git rebase --continue