有没有办法让新分支自动跟踪与创建该分支的现有分支相同的远程终端?
说我有一个本地分支foo
,该分支跟踪一个远程origin/bar
。我可以基于baz
明确地创建一个新分支foo
并通过执行以下操作来跟踪origin/bar
:
git checkout foo
git checkout -b baz origin/bar
但是有没有一种通用的方法可以从baz
创建分支foo
并使其与foo
跟踪同一远程,而不管该远程恰好是什么?
答案 0 :(得分:2)
但是有没有一种通用的方法可以从
baz
创建分支foo
并使其与foo
跟踪同一远程,而不管该远程恰好是什么?
是的,但是有点复杂。 Git就是这样,大约有十二种 1 不同的方法可以做到这一点,但是我们这里只选一个。
首先,让我们看一下所有重要的部分:
foo
和baz
。origin/bar
(全名refs/remotes/origin/bar
)之类的远程跟踪名称。而且,任何(本地)分支名称都有一个可选的上游设置。通常,某些本地分支的上游是一个远程跟踪名称(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
。
在这种情况下,您要创建一个名为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
设置起点来创建分支(并且可以根据需要切换到该分支)。在这种情况下,至少在默认情况下,foo
和git 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
仅针对remote
和merge
设置即可做到,
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