更改远程分支的本地参考

时间:2013-12-01 09:30:19

标签: git

我有两个存储库绑定到我的工作目录。

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

我该怎么做?

1 个答案:

答案 0 :(得分:13)

在我回答之前,我想在这里更改这些术语,因为您使用某些单词的方式与大多数git文档中使用的单词和方法不匹配。

首先,让我们谈谈git存储库中提交生成的图形。

每次在存储库中创建提交时,都必须指定以下项。其中许多是隐含的;实际上,git commitgit merge(这两个主要的提交创建者)将为您查找所有这些内容:

  • 父提交或一组父提交
  • 作者和作者日期" (通常与提交者相同)
  • 提交者和"提交日期" (通常与作者相同)
  • a" tree" (通常取自索引/暂存区域)和
  • 提交消息(通过-m参数,或git commit激活您的编辑器等)

Git结合了所有这些并创建了一个新的唯一SHA-1值 - 那些笨拙的40个字符的字符串,如9c4ea50db79d3ce6fe3abccf20f1af27abae45b2 - 提交(它存储此提交对象)回购,由其SHA-1 ID)。如果提交是普通提交,则它有一个父项,git commitHEAD创建之前不久.git通过git commit找到(git存储在git merge目录中)新提交。如果它是" root commit"就像新回购中的第一次提交一样,它有没有父母。如果它是"合并提交" (例如,由.git创建),它具有至少两个父ID(这些ID来自o-o-o-o-o-o-o \ / o-o-o 目录中的文件git store)。存储在任何给定提交中的父项是原始SHA-1 ID。

因此,给定任何一个提交SHA-1 ID,您可以从存储库中读取提交并获取其父提交。读那些让你的父母。继续,直到您到达根提交,并且您可以绘制一些内容,其中包含可能的分支点和合并点:

o

这是一个提交图,有10个提交"节点" (- s)其中一些分支然后合并回来。我在\ /master个字符的节点之间绘制了线条

当我们使用git时,我们经常将这些行称为#34; branches",这是一个合理的名称,但是" branch"的另一个含义。

接下来,让我们定义一个"分支" (或者#34;本地分支")这样,这就是git真正起作用的方式:一个(本地)分支是一个名称,如developurl,存储SHA-1 ID并且具有另一个特殊属性。特殊属性是当我们进行新提交时存储的ID 更改,以便branch-name始终标识"提示"分支机构。

请记住,每次提交都有 ID,但不包含任何 ID。当你进行新的提交时,新的提交"指回" (通过这些存储的ID)到旧的,但旧的永远不会改变。仅仅给出父ID而难以找到子ID,但是仅仅给出子ID的父ID很容易找到。所以只要分支名称"指向"分支的提示,我们可以找到"分支的其余部分"容易。因此git只是保证本地分支名称始终标识分支的提示。

(有点不幸的是,&#34;分支&#34;意味着两者&#34;本地名称持有分支小费的ID&#34; < em>和&#34;通过从尖端开始并向后工作形成的提交链#34;几乎总是显而易见的是哪一个将被使用,但只有&#34;几乎&#34;。)

现在让我们定义&#34; remote&#34;:远程是你组成的名称并放在你的本地git存储库中,用于记住某些其他的东西 git存储库,通常在另一台计算机上,属于其他人。远程有一个remote.origin.url(或者有时几个:remote.origin.pushurl,可选remotes/origin/master ,这就是git将如何获取和推送到另一个repo。

当然,其他repo有(本地)分支 - 分支名称指向提交提交 - 事实证明我们经常想知道其他repo的本地分支名称和提示提交 - 或者更准确地说,他们上次检查时他们是什么。 (它们已经过时了,所以我们不时刷新它们。)这些就是成为&#34;远程分支机构&#34;。所以现在我们可以定义&#34;远程分支&#34;通过示例稍微宽松一点:远程分支master是远程origin上本地分支origin的副本,上次我们有机会连接到{{1}并问你&#34; master中的内容是什么?&#34;

更准确地说:每个远程分支remotes/R/B都是远程 B 上本地分支 R 的副本我们最后一次检查并保存了它。

现在我们只需要一个&#34;跟踪分支&#34;的另一个定义。 跟踪分支是一个本地分支,我们告诉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/harehare部分来自branch.greyhound.merge行,racetrack部分来自branch.greyhound.remote

如果你把它遗漏,Git会提供remotes/部分。因此,您可以通常只编写remotes/origin/master而不是origin/master。 (如果你创建歧义,有一些例外,例如,如果你创建一个名为origin的本地分支,它会变得棘手。但只要你不这样做,你就可以省略{{1}人们和git经常把它留下来。)

最后一点注意,因为我有上面的所有其他定义。特殊参考remotes/通常是&#34;符号引用&#34;。符号引用包含另一个引用的名称,通常是本地分支名称。这就是git知道如何将本地分支调整到新的分支提示:如果您在分支主文件&#34;上,HEAD包含HEAD,那么{{1添加新提交并更新ref: refs/heads/master。如果git commit包含原始SHA-1值,master会像往常一样添加新提交,然后更改HEAD以获得新的SHA-1,但没有本地分支名称指向新提交。这是&#34;分离的HEAD&#34;条件。


呼!好的,现在回到手头的问题。你即将绊倒目前在git中修复的烦恼。

您想要或需要:

  1. 在名为git commit的遥控器上,必须有一个带HEAD分支的git仓库
  2. 在名为origin的遥控器上,必须有一个带master分支的git仓库
  3. 在您的本地仓库中,您希望develop成为master的跟踪分支
  4. 在您的本地仓库中,您希望master成为origin/master的跟踪分支
  5. 当您trunk时,您希望将develop/master推送到git push origin,并且可能根本没有推出master
  6. 当您master时,您希望trunk被推动开发git push develop,并且可能根本没有推动trunk
  7. 当你master(没有其他参数)时,你想......好吧,我不确定你想要什么,但我会在下面猜一下。
  8. 步骤1到4只需要完成一次。如果尚未在其中一个或两个上创建分支master,您可以执行以下操作:

    git push

    (如果你的git推送足够新,让master)一次完成所有事情。或者,如果您有,可以使用git push -u origin master:master git push -u develop trunk:master ,或者如果您愿意,可以使用-u完全手动进行跟踪。但是,如果需要,可以通过这种或那种方式在远程存储库上创建分支,然后选择它们(作为&#34;远程分支机构&#34;在您的本地存储库中)并将您的本地分支机构设置为&#34; track&#34 ;远程分支。

    剩下的步骤。这些有点令人困惑。

    在最新版本的git(至少1.7以后)中,有一个配置设置--set-upstream会影响git config在省略refspec时的工作方式,即push.default项目5到7中的命令。您需要将其设置为git push。这绝不是默认设置,因此您必须运行:

    push

    设置它。

    如果你运行裸upstream(如在#7中),git使用相同的跟踪分支信息来选择远程。所以,现在您已经更改了git config push.default upstream ,如果您在分支git push上运行push.default,那么您实际上将运行master,如果您和#39;在分支git push上运行git push origin master:master,您实际上将运行trunk

    如果您只是让git push设置执行此操作,并在git push develop trunk:master上运行push.default upstream,那么,您没有告诉它推动您的名为git push develop的本地分支。因此,要使5和6工作,您需要两个不同的 git配置项。

    如果您运行master(没有refspec参数),trunk会查找git push remote,并在设置时使用该git push。因此,您可以设置remote.remote.pushremote.origin.push master:master。现在remote.develop.push trunk:master有一个设置,不需要使用git push develop