我有两个存储库绑定到我的工作目录.
git remote show origin * remote origin Fetch URL: ssh://project.git/ Push URL: ssh://project.git/ HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date) git remote show develop * remote develop Fetch URL: ssh://projecttest.git/ Push URL: ssh://projecttest.git/ HEAD branch: master Remote branch: master new (next fetch will store in remotes/develop) Local ref configured for 'git push': master pushes to master (local out of date)
据我所知,本地分支以这种方式引用远程分支:
远程origin/master
指向本地分支master
远程develop/master
指向本地分支master
我想要实现的是更改develop/master
远程分支的此引用.我希望它指向trunk
本地分支
remote develop/master
应该指向本地分支trunk
我该怎么做?
在我回答之前,我想在这里更改术语,因为您使用某些单词的方式与大多数git文档中使用的单词和方法不匹配.
首先,我们来谈谈git存储库中提交生成的图形.
每次在存储库中创建提交时,都必须指定以下项.其中许多是隐含的; 其实,git commit
和git merge
(这是两个原则提交创造者)将看都起来为你:
父提交或一组父提交
作者和"作者日期"(通常与提交者相同)
提交者和"提交日期"(通常与作者相同)
"树"(通常取自索引/临时区域),和
提交消息(通过-m
参数,或git commit
激活您的编辑器等)
GIT中结合了所有这些和使得一个新的唯一SHA-1值的那些笨重的40个字符的字符串等9c4ea50db79d3ce6fe3abccf20f1af27abae45b2
-即是提交(它存储在回购此提交对象,通过其SHA-1的ID).如果提交是普通提交,则它有一个父级,它在创建新提交之前不久git commit
找到via HEAD
(git存储在.git
目录中)git commit
.如果它是一个"root commit",就像新repo中的第一次提交一样,它没有父项.如果它是"合并提交"(git merge
例如,由其创建),则它至少有两个父ID(这些ID也来自目录中的文件git store .git
).存储在任何给定提交中的父项是原始SHA-1 ID.
因此,给定任何一个提交SHA-1 ID,您可以读取存储库中的提交并获取其父提交.读那些让你的父母.继续,直到您到达根提交,并且您可以绘制一些内容,其中包含可能的分支点和合并点:
o-o-o-o-o-o-o \ / o-o-o
这是一个提交图,其中有十个提交"节点"(o
s),其中一些已经分支然后合并回来.我在节点-
\
和/
字符之间绘制了线条.
当我们使用git时,我们经常将这些行称为"分支",这是一个合理的名称,但"分支"还有另一个含义.
接下来,让我们用这种方式定义一个"分支"(或"本地分支"),这就是git真正使它工作的方式: 一个(本地)分支是一个名称,如master
或者develop
,它存储一个SHA-1 ID并且具有另一个特殊财产. 特殊属性是我们进行新提交时存储的ID会更改,因此branch-name始终标识分支的"提示".
请记住,每个提交都有其父 ID,但不包含任何子 ID.当你进行新的提交时,新的提交"指回"(通过这些存储的ID)到旧的提交,但旧的提交永远不会改变.很难找到仅给出父ID的子ID,但很容易找到仅给出子ID的父ID.因此,只要分支名称"指向" 分支的尖端,我们就可以轻松找到"分支的其余部分".因此git只是保证本地分支名称始终标识分支的提示.
(这是一个位不幸的是"分支"是指两个 "本地名称保持分支的尖端的ID" 和 "的犯下由起始于尖端和向后加工形成的链."这几乎总是显而易见哪一个是在什么时候使用,但只是"差不多".)
现在让我们定义"远程":远程是你组成的名称并放在你的本地git存储库中,用于记住关于其他 git存储库的东西,通常在另一台机器上并属于其他人. 一个遥控器有一个url
(或者有时几个:remote.origin.url
和可选remote.origin.pushurl
的),这就是git将如何从另一个存储器获取和推送.
当然,其他repo有(本地)分支 - 分支名称指向提交提交 - 事实证明,我们经常想要知道其他repo的本地分支名称和提示提交是 - 或者更确切地说,他们最后一次检查是什么 (它们已经过时了,所以我们不时刷新它们.)这些就是"远程分支".所以现在我们可以通过示例稍微松散地定义"远程分支":远程分支remotes/origin/master
是本地分支的副本master
,在远程origin
,上次我们有机会连接origin
并询问它"你的内容是什么master
?"
更准确地说:每次远程分支都是我们上次检查并保存时远程本地分支的副本.remotes/R/B
B
R
现在我们只需要一个"跟踪分支"的定义. 跟踪分支是一个本地分支,我们告诉git有一个相应的远程,并在该远程上有一个相应的分支名称. 我们告诉git这两件事的低级方式是配置两个字符串git config
.例如,假设我们希望本地分支greyhound
跟踪racetrack
名为的远程分支hare
.要在最低级别执行此操作,我们执行此操作:
git config branch.greyhound.remote racetrack git config branch.greyhound.merge hare
(使事情变得复杂 - 这似乎是一个历史事故 - 实际的跟踪是通过fetch
遥控器的配置进行映射的.但remote.racetrack.fetch
几乎总是设置为读取+refs/heads/*:refs/remotes/racetrack/*
.在大多数情况下,我们可以假设refs/remotes/
部件是常数.)所以,再次,在底层,当git想要看看是否greyhound
已经赶上时hare
,它真正做的是看remotes/racetrack/hare
.该hare
部分来自于branch.greyhound.merge
线,以及racetrack
部分来自branch.greyhound.remote
.
remotes/
如果你把它留下来,Git会提供这个部分.因此,而不是remotes/origin/master
你通常可以写origin/master
.(如果你创建歧义,有一些例外,例如,如果你创建一个名为origin
它的本地分支变得棘手.但是只要你不这样做,你可以省去remotes/
,而且人们和git - 经常会留下它出.)
最后一点注意,因为我有上面的所有其他定义.特别参考HEAD
通常是"象征性参考".符号引用包含另一个引用的名称,通常是本地分支名称.这就是git知道如何将本地分支调整到新的分支提示:如果你是"在分支主机上",HEAD
包含ref: refs/heads/master
,那么git commit
添加一个新提交并进行更新master
.如果HEAD
包含原始SHA-1值,git commit
则像往常一样添加新提交,然后更改HEAD
为具有新SHA-1,但没有本地分支名称指向新提交.这是"独立的HEAD"条件.
呼!好的,现在回到手头的问题.你即将绊倒目前正在git中修复的烦恼.
您想要还是需要:
在远程命名origin
,必须有一个master
分支的git仓库
在远程命名develop
,必须有一个master
分支的git仓库
在您的本地仓库中,您希望master
成为跟踪分支origin/master
在您的本地仓库中,您希望trunk
成为跟踪分支develop/master
当你git push origin
想要把你的东西master
推到原点时master
,可能根本就没有trunk
推动
当你git push develop
想要让你trunk
得到发展的时候master
,可能根本就没有master
推动
当你git push
(没有额外的参数),你想要......好吧,我不确定你想要什么,但我会在下面猜测.
步骤1到4只需要完成一次.如果master
尚未在其中一个或两个上创建分支,您可以执行以下操作:
git push -u origin master:master git push -u develop trunk:master
(如果你的git push足够新-u
)可以一次完成所有事情.或者,--set-upstream
如果您有,可以使用,或者git config
如果您愿意,可以完全手动进行跟踪.但不管怎样,如果需要,在远程存储库上创建分支,然后选择它们(作为本地存储库中的"远程分支")并设置本地分支以"跟踪"远程分支.
剩下的步骤就是这样.这些有点令人困惑.
在最新版本的git(至少1.7以后)中,有一个配置设置push.default
会影响git push
当你省略refspec时的工作方式,即第push
5到7项中的命令.你需要将其设置为upstream
.这绝不是默认设置,因此您必须运行:
git config push.default upstream
设置它.
如果你运行裸机git push
(如在#7中),git使用相同的跟踪分支信息来选择远程.所以在这里,既然你已经push.default
改变了,如果你在分支master
和运行git push
,你实际上将运行git push origin master:master
,如果你在分支trunk
和运行git push
,你实际上将运行git push develop trunk:master
.
但是,如果您只是让push.default upstream
设置执行它的操作,并git push develop
在您打开时运行,那么master
,您没有告诉它推送您的本地分支命名trunk
.因此,要使5和6工作,您需要两个不同的 git配置项.
如果你运行(没有refspec参数),查找,并使用它,如果它已设置.因此,你可以设置和.现在有一个设置,不需要使用.git push remote
git push
remote.remote.push
remote.origin.push master:master
remote.develop.push trunk:master
git push develop
push.default