使新的git分支跟踪相同的远程分支

时间:2019-05-15 19:43:04

标签: git

有没有办法让新分支自动跟踪与创建该分支的现有分支相同的远程终端?

说我有一个本地分支foo,该分支跟踪一个远程origin/bar。我可以基于baz明确地创建一个新分支foo并通过执行以下操作来跟踪origin/bar

git checkout foo
git checkout -b baz origin/bar 

但是有没有一种通用的方法可以从baz创建分支foo并使其与foo跟踪同一远程,而不管该远程恰好是什么?

3 个答案:

答案 0 :(得分:2)

  

但是有没有一种通用的方法可以从baz创建分支foo并使其与foo跟踪同一远程,而不管该远程恰好是什么?

是的,但是有点复杂。 Git就是这样,大约有十二种 1 不同的方法可以做到这一点,但是我们这里只选一个。

首先,让我们看一下所有重要的部分

  • 您有自己的本地分支名称,在您的示例中为foobaz
  • 有诸如origin/bar(全名refs/remotes/origin/bar)之类的远程跟踪名称。
  • 每个分支名称或远程跟踪名称都指向该提交哈希ID。
  • 而且,任何(本地)分支名称都有一个可选的上游设置。通常,某些本地分支的上游是一个远程跟踪名称(Git将该名称称为“远程跟踪分支”),该名称使用相同的基本名称但带有一个远程名称作为前缀。例如,master通常将origin/master设置为其上游。但是,如您的示例所示,分支的上游不需要匹配:foo的上游可以是origin/bar

    (也可以将 local 分支设置为另一个本地分支的上游;这的行为与您期望的一样。在内部,这是通过将remote的一半设置为由两部分组成的上游设置.,这意味着您自己的存储库。但是我们在这里忽略了这些详细信息。)

fphillipe mentioned一样,我们拥有git branch --set-upstream-to,它可以随时设置任何分支的上游。如果已经有一些上游集,则将其替换。如果没有上游设备,那么现在有。

我们还有两种创建新分支名称的方法:

  • git branch name [start-point]创建一个名为 name 的新(本地)分支。以该名称存储的初始哈希ID由 start-point 给出;如果您省略 start-point ,则初始哈希ID是git rev-parse HEAD产生的值。

  • git checkout -b name [start-point]创建一个名为 name 的新(本地)分支,然后以同一名称执行一个git checkout。从本质上讲,它等效于先运行git branch,然后运行git checkout


1 "Ew, gross"


目标

在这种情况下,您要创建一个名为baz的本地分支,将其 hash 设置为与foo匹配,并将其上游设置为{{1} }的上游,即foo。也就是说,创建origin/bar后,您需要:

baz

产生与以下相同的输出:

git rev-parse baz

-这意味着相同的提交是每个分支的尖端提交-但您需要:

git rev-parse foo

产生git rev-parse --symbolic-full-name baz@{upstream}

这两个创建命令可以但并非总是都设置新创建分支的上游。您可以使用refs/remotes/origin/bar参数来强制他们进行设置,也可以使用--track参数来强制他们不要进行设置。 --no-track标志使用远程跟踪名称,因此,如果您首先确定--track的上游是foo,则可以编写:

origin/bar

(或者如果您不想同时签出新分支,则与git checkout -b baz origin/bar 相同)。但这有两个错误:

  • 这要求您手动找到git branch的上游。您想使它自动化。
  • 也许更重要的是,它创建foo指向与baz相同的提交。如果origin/bar指向不同提交,则违反了其中一种愿望。

因此,必须分几部分来完成这项工作。首先,您将使用本地名称foo设置起点来创建分支(并且可以根据需要切换到该分支)。在这种情况下,至少在默认情况下,foogit branch都将设置为新分支的上游,但是使用git checkout可以使您完全明确,也可以将--no-track转换为原始哈希ID。通常所有这些都是不必要的, 2 ,但是如果您想获取原始哈希ID,请执行以下shell片段操作:

foo

如果name=baz start=foo hash=$(git rev-parse ${start}^{commit}) || exit 无法将git rev-parse解析为原始哈希ID,或者foo无法识别提交,则foo会向stderr生成错误消息并退出非零值,然后git rev-parse将退出您的shell片段。

然后:

|| exit

将尝试创建分支名称git branch $name $hash || exit ,指向所需的哈希值。

我们还需要找到上游名称,$name还是要使用的命令:

git rev-parse

和以前一样,如果upstream=$(git rev-parse --symbolic-full-name ${start}@{upstream}) || exit 失败,我们将退出shell片段,让git rev-parse打印适当的错误。现在我们有了上游,我们可以使用git rev-parse进行设置:

git branch --set-upstream-to

2 在命令行上,您只需要运行一个命令并观察:如果它做了您想要的,就可以了,如果没有,请在执行时进行更正。但是,从 script 来看,通常很难看到发生了什么或可能发生了什么。最好使用副作用尽可能少的东西。因此,我们尽可能将每个Git命令分解为直接管道命令。在本示例中,我并没有将其发挥到极致,因为这太烦人了,但是我将展示git branch --set-upstream-to $name $upstream 操作。


代码

以正确的顺序将各个部分放在一起,再加上一些参数检查和使用git rev-parse来避免所有-e的使用,我们得到了完整(但未经测试)的shell脚本:

|| exit

在对此进行测试之后,将其作为可执行Shell脚本编写在#! /bin/sh -e usage() { echo "usage: $0 branch-name start-point" } case "$#" in 2) ;; *) usage 1>&2; exit 1;; esac name="$1" start="$2" hash=$(git rev-parse ${start}^{commit}) upstream=$(git rev-parse --symbolic-full-name ${start}@{upstream}) git branch $name $hash git branch --set-upstream-to $name $upstream 中的某个位置,并调用它(例如)$PATH,然后:

git-branch-with-upstream

将调用该脚本,该脚本将创建git branch-with-upstream baz foo 指向与baz相同的提交,并且foo的上游与foo的上游。

您现在知道如何编写新的Git命令!

答案 1 :(得分:0)

看看--set-upstream-to中的git branch

git branch (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]

从文档中

-u <upstream>, --set-upstream-to=<upstream>

Set up <branchname>'s tracking information so <upstream> is
considered <branchname>'s upstream branch. If no <branchname> is
specified, then it defaults to the current branch.

答案 2 :(得分:0)

要将一个分支的所有设置复制到另一个:

git config --local --get-regexp ^branch\\.$one \
| sed "s,^,git config ,;s,$one,$another," \
# | sh -x

仅针对remotemerge设置即可做到,

git config --local --get-regexp "^branch\\.$one\\.(remote|merge)" 

我倾向于通过如上所述构建命令列表来做这些事情,其他人可能更喜欢

git config --local --get-regexp "^branch\\.$one\\.(remote|merge)" \
| while read config value; do
        git config ${config/.$one./.$another.} "$value"
  done