我们在组织中使用了fork模型,并且我试图将更新从上游分支合并到本地分支。
这是我的git设置。
kartik@ ~/sourcecode/myproject (defect-875) $ git remote -v
origin git@github.com/kartik/myproject.git (fetch)
origin git@github.com/kartik/myproject.git (push)
upstream git@github.com:MyOrg/myproject.git (fetch)
upstream git@github.com:MyOrg/myproject.git (push)
上游有两个分支机构
主控
开发
我需要将本地分支与devel
上游分支同步。
这是我尝试过的
git fetch upstream
git merge upstream/defect-875
defect-875是我的本地分支。
我总是收到此错误消息
合并:上游/缺陷875-我们无法合并
我也尝试过
kartik@ ~/sourcecode/myproject (defect-875) $ git merge upstream/devel -m "Merging from seo redirect."
merge: upstream/devel - not something we can merge
如何解决此问题?
答案 0 :(得分:1)
我认为您应该说git merge upstream/devel -m "Merging from devel"
(已检查出fault-875,以便我们在同一页面上。)
答案 1 :(得分:0)
eftshift0's answer是正确的选择,但听起来您应该学习一些Git技巧。
关于Git的第一件事是,它主要与 commits 有关。分支-或实际上是分支名称(请参阅What exactly do we mean by "branch"?)-存在于Git中,以便Git和我们都能找到提交。
您可能已经知道提交实际上是源树的快照。 (如果您不这样做,那么现在就可以了!)但是它还有更多点。首先,每个提交都以其哈希ID的形式具有唯一的“真实名称”。分支名称是表达某些提交的真实名称的一种方式(哈希ID),git rev-parse
将为您显示实际的哈希ID:
$ git rev-parse master
c05048d43925ab8edcb36663752c2b4541911231
这些大的丑陋ID似乎是随机的,但实际上完全由提交本身的内容确定。这些内容非常简短-这是上面的提交,其中@<address>
受到了一些限制,以减少垃圾邮件:
$ git cat-file -p c05048d43925ab8edcb36663752c2b4541911231 | sed 's/@/ /'
tree a446a29ef7ca90d9c64825fb00a0f1e1a099ca18
parent e9983f8965c0875cc6727e9644c84ff1dfc99372
author Junio C Hamano <gitster pobox.com> 1536096807 -0700
committer Junio C Hamano <gitster pobox.com> 1536096807 -0700
Git 2.19-rc2
Signed-off-by: Junio C Hamano <gitster pobox.com>
上面的 tree 行是提交如何保存源快照的方式(通过使用另一个Git内部对象)。 author 和 committer 行告诉我们谁进行了提交,以及何时— 1536096807表示Tue Sep 4 14:33:27 2018
。 parent 行给出了在该提交之前 的提交的丑陋哈希ID。
我们说其中每个具有哈希ID的事物都指向对象。有关更多信息,请参见Think Like (a) Git,但对于此答案,让我将其绘制如下:
... <-c05048d43925ab8edcb36663752c2b4541911231 <--master
名称 master
指向此提交,指向较早的提交e9983f8965c0875cc6727e9644c84ff1dfc99372
。该较早的提交指向一个较早的提交,依此类推。
您在自己的存储库中拥有所有这些分支名称,例如master
和defect-875
。它们不依赖您自己的Git之外的任何东西。它们指向您在本地也具有的提交,并且这些提交(包括其快照和其父提交以及那些提交的快照,一直追溯到历史中)也不依赖于您自己的Git之外的任何内容。
但是您确实从其他一些Git中得到了一些 提交。您可以使用Internet通过让Git调用那些Git来实现。他们的Git存储库中有 their 提交以及 their 分支名称。所有提交都具有唯一的哈希ID,但是如果提交具有与 you 的某些提交具有相同的真实名称的相同哈希ID,则它们和根据定义,您具有相同的提交。
git fetch
获得您没有的提交他们的分支名称不必匹配,但是提交哈希ID do 必须匹配。它们匹配,或者您有提交,或者它们有您没有的提交。因此,您的Git调用他们的Git并说:您拥有什么名称,它们的提交哈希ID是什么?他们的Git为您的Git提供了此列表,而您的Git自言自语:啊,我有这个或 hm,我没有那个。然后,您的Git会向他们的Git列出他们拥有的提交列表,您的Git 想要,然后他们的Git将这些提交(包括快照)打包并发送过来。
在此过程结束时,您拥有所有提交(包括您已经拥有的所有提交) plus 所有提交。请注意,它们不仅向您发送最尖端的提交(分支名称直接指向它们),而且还向您发送父提交,父父提交等等,以便您获得 connect back的提交您自己的提交。
git fetch
也获得了它们的分支名称;现在呢?您也有他们的分支名称。但是这些是他们的分支名称,所以现在您的Git 重命名这些东西。如果您的Git使用git fetch upstream
调用了他们的Git,则您的Git 重命名他们的master
,将其命名为upstream/master
,并重命名其devel
,将其命名为upstream/devel
。
我们可以这样绘制提交,使用回合o
代表实际的哈希ID,尽管我现在必须开始猜测很多提交它们的方式没错在运行git fetch upstream
之前,您需要执行以下操作:
... <-o <-o <-o <-- master
\
o <-- defect-875
您的defect-875
提交指向您的master
分支的尖端,该分支指向更早的提交,依此类推。不过,一旦运行git fetch upstream
,您将获得更多类似的内容:
o--o <-- upstream/devel
/
o--o--o <-- upstream/master
/
...--o--o--o <-- master
\
o <-- defect-875
(绘制箭头太难了,所以我已经用线代替了其中的大部分,只记得它们总是指向后)。
运行git merge
时,必须告诉Git 要与之合并的提交。通常,您可以给它指定一个分支名称,或使用upstream/devel
之类的远程跟踪名称。该名称解析为提交哈希ID,就像我在上面显示的那样,您可以运行git rev-parse
来查看其工作原理。 因为 git fetch
获得了他们的devel
并将其重命名为您自己的upstream/devel
,所以它可以正常工作。如果尚未运行git fetch upstream
,则必须首先执行该操作,以便您的Git拥有提交并已将其devel
重命名为upstream/devel
。
此时,所有工作都在您自己的存储库中进行。假设我的图纸很准确;但是,我们将其简化为有趣的名称,然后将HEAD
一词附加到您现在已签出的名称上。我还将为三个有趣的提交输入一个字母的名称:
o--R <-- upstream/devel
/
o--o--o
/
...--o--o--B
\
L <-- defect-875 (HEAD)
运行git merge upstream/devel
会发现您当前的提交或HEAD
的提交L
(对于Left或Local或--ours
);您标记为upstream/devel
的提交,即R
提交(用于Right或Remote或--theirs
);并使用L
和R
返回共同的起点,即提交B
(对于Base)。
然后,您的Git实际上将运行两个git diff
命令,以查看您所做的更改-B
与L
的不同之处,并查看它们的更改,即, B
与R
有什么区别:
git diff --find-renames <hash-of-B> <hash-of-L> # what we did
git diff --find-renames <hash-of-B> <hash-of-R> # what they did
现在, Git结合了合并-这两组更改。如果它们容易组合,则Git会将组合的更改应用于与提交B
关联的快照,并从结果中进行新的提交。这是合并提交,一种特殊的提交。使其与众不同的原因仅仅是,它有两个父母而不是一个父母:它首先列出自己的提交L
作为其第一父提交,然后列出他们的提交R
作为其第二父提交。
如果我们将图形上下颠倒,可能会有所帮助,所以我将在此处进行。结果看起来像这样:
L----------------M <-- defect-875 (HEAD)
/ /
...--o--o--B /
\ /
o--o--o /
\ /
o--R <-- upstream/devel
此新提交M
位于您自己的defect-875
分支上。
upstream
现在,如果您仍然获得授权,则可以使用git push
在您的Git引用为defect-875
的Git存储库上创建一个upstream
分支,使用:
git push upstream defect-875
这让您的Git调用他们的Git,向他们 提供您拥有他们他们没有的提交列表-在这种情况下,恰好是两个提交L
和M
,然后向他们的Git建议他们使用提交defect-875
作为提示提交,创建一个名为M
的分支。
如果他们服从所有这些请求和建议,您的Git会记住他们是这样做的,并将名称upstream/defect-875
添加到您自己的名称集中:
L----------------M <-- defect-875 (HEAD), upstream/defect-875
/ /
...--o--o--B /
\ /
o--o--o /
\ /
o--R <-- upstream/devel
您自己的分支defect-875
不会发生任何变化:您的名字defect-875
仍会标识您的提交M
(通过其实际的哈希ID,无论如何)。您只给了他们的Git这两个提交,并让他们的Git设置了他们的名称defect-875
即可与您的匹配。
如果愿意,您现在可以将自己的分支机构defect-875
的上游设置为名称upstream/defect-875
:
git branch --set-upstream-to=upstream/defect-875 defect-875
如果您想在运行git push
时同时执行这两项操作,则可以通过在-u
上添加git push
标志来一次完成所有操作:
git push -u upstream defect-875
但这只是一个方便的优化。