我们必须处理另一个团队回购,但出于各种原因,我们希望保持我们的开发工作不被看到,直到它准备推送到他们的回购。
我克隆了他们的repo,删除了.git文件夹,然后用文件创建了一个新的repo。这让我们起步并运行,但我不确定现在是将更改从其回购合并到我们的回购的最佳方式。
有没有更好的设置,我们可以孤立地工作,但没有在合并之上有这么尴尬的时间?
答案 0 :(得分:1)
删除.git
是不利的。
再次克隆远程仓库。您可以添加其他遥控器 git remote add yourrepo http://urlOfYourRepo
确保将不同步分支的默认推送/提取回购设置为yourrepo:git push -u yourRepo
以设置默认上游
您可以随时git fetch origin
对您的回购进行远程回购更改,然后将其合并到您的回购中。
使用git push origin yourCommit
,您可以将您的提交(或分支)推送到远程仓库。
答案 1 :(得分:1)
删除.git
文件夹后,您删除了历史记录。然后通过从这些文件创建一个新的repo,你开始了一个新的历史记录,在git的视图中,它是无关的。即使您在进行任何更改之前已提交,仍然会创建新提交(内容完全相同)。
你想要的是你的团队的回购保留上游回购的历史记录,以便你的回购知道你的变化与历史相关,然后它(相对)容易合并上游变化。然后,您只需控制推送到该原点的内容即可控制上游可见性。
这仍然可以实现,但确切的步骤取决于有关您当前状态的一些问题。我将不得不做出一些假设,所以请评论这些假设是否错误,我可以尝试相应地调整答案。
所以大概是你创建了一个新的仓库,你有一个名为origin
的远程开发人员,你的开发人员可以从中克隆他们的本地仓库。 (继续前进,我将调用origin
,以及您从中获取第一个快照的原始存储库,我将调用upstream
。)
我还假设您的origin
中正在进行积极的开发,因此仅从clone
重新upstream
就会出现问题。并且您正希望将upstream
的更改集成到origin
。
第一步,使用origin
的克隆进行操作,即可获取upstream
历史记录。
git remote add upstream url/of/upstream/repo
git fetch upstream
接下来,您需要整合历史记录。有几种方法可以做到这一点。最好的长期结果来自历史重写,但需要您的团队之间进行一些协调。
理想情况下,您会告诉团队中的每个人push
他们的工作是origin
;它不需要完全合并,但所有分支都需要push
。在push
工作之后,他们应该丢弃他们的克隆并等待你告诉他们重写完成,此时他们会创建origin
的新克隆(并且,可选地,添加{{ 1}}遥控器。)
如果这种协调水平不可能,仍然可以进行重写;但是对于部分或全部开发人员来说可能会有更多的工作,因为他们必须在upstream
origin
时执行他们自己的迁移clone
fetch
} d(或在重写之前完成了你的最后fetch
)。在这种情况下,最好使用非重写选项(稍微多一点)。
让upstream
编辑您队伍的所有历史记录(或在克隆您的工作回购时复制它),接下来需要在origin
历史记录中确定与您的master
存储库中的初始提交。
如果这是标记版本,那可能会使事情变得简单;但我假设它只是当时git diff
上的任何内容。但即使在这种情况下,如果您知道何时执行此操作,您应该能够跟踪正确的提交并通过O
验证它是否与您的初始提交相匹配。
所以你找到了提交,我们在下图中标记X -- X -- O -- X -- X -- X <--(upstream/master)
o -- A -- B <--(master)(origin/master)
\
C <--(someBranch)
;为方便起见,您可能想要标记它。
o
现在,最简单的做法是重新父母O
,以便替换它的父母A
。另一个选择,产生一个&#34;清洁&#34;结果,是重新父C
和o
,将O
替换为 git filter-branch --parent-filter "sed \"s/$(git rev-parse master~2)/$(git rev-parse origin/master~3)/g\"" -- --branches
作为其父级。后者可能稍微复杂一点,但没有你想象的那么多;所以让我们来看看如何做到这一点。在上面的示例中,您可以使用类似
X -- X -- O -- X -- X -- X <--(upstream/master)
|\
| A* -- B* <--(master)
\
C* <--(someBranch)
o -- A -- B <--(refs/original/refs/heads/master)(origin/master)
\
C <--(refs/original/refs/heads/someBranch)
应该给你
git push -f
然后,您可以强制推送(origin
)所有重写的分支到origin
,或者从新的回购中重新创建original/refs/heads
。
请注意,您进行重写的本地仓库将在origin
下有新的refs,表示分支的预重写位置。另请注意,origin
的远程跟踪引用尚未更新(直到您执行强制推送,或直到您删除origin
远程并使用反映重写的远程重新添加它。
那么......如果你决定重写怎么办?那么,在这种情况下,您可能希望拥有一个&#34;集成回购&#34;,从upstream
克隆并添加git replace
。在集成仓库中,您将设置o
映射,告诉git&#34;每当遇到对象O
时,请使用对象git replace
代替&#34;。这篇&#34;论文超过&#34;问题。它可能有一些怪癖(请参阅replace
文档),但理想情况下,您可以在一段时间过后停止依赖X -- X -- X -- O -- A -- B -- C <--(upstream/master)
o -- D -- E <--(master)
映射(和集成存储库)。开发者&#39;历史不会像重写一样干净,但是没有必要切换到重建的存储库。
这里的想法是,最终历史将足够组合&#34;如果没有替换,git将会理解该怎么做。这将与如何计算合并基数有关。考虑一个简单的案例。
upstream
现在您要将master
更改合并到git replace master~2 upstream/master~3
。在您的集成回购中,您已经说过
X -- X -- X -- O -- A -- B -- C <--(upstream/master)
:
o -- D -- E <--(master)
我们可以画成
X -- X -- X -- O -- A -- B -- C <--(upstream/master)
\
D -- E <--(master)
默认情况下使用git命令&#34;请参阅&#34;
git checkout master
git merge upstream/master
如果你说
的意思O
计算出的合并基数为X -- X -- X -- O -- A -- B -- C <--(upstream/master)
\ \
D ---- E ---- M <--(master)
,git将&#34;认为&#34;它给你了
X -- X -- X -- O -- A -- B -- C <--(upstream/master)
: \
o --- D --- E --- M <--(master)
真的是
master
在此示例中,upstream
是唯一接收master
更改的分支,此时upstream/master
的历史记录会追溯到upstream/master
;因此,下次将master
合并到C
时,合并基础应为X -- X -- X -- O -- A -- B -- C <--(upstream/master)
\
o --- D --- E --- M <--(master)
,并且不再需要替换(因此可以在任何克隆中执行,而不是需要进行在一个特别设置的整合回购中。)
现在我提到开发人员&#39;历史不会像&#34;清洁&#34;,显而易见的是,在你停止使用替换后的最终状态,我们有
D
所以&#34;血统&#34; E
,M
和M
的某些内容有所不同。特别是C
将E
合并到{{1}}中的结果并不明显。这可以被看作是一个邪恶的合并&#34;,虽然它没有那些在某种意义上的默认合并(不使用替换)会产生合并冲突。