9

我正在搜索 git 命令以了解与现有分支关联的上游(如果有)。
(某种与“write”命令相关的“read”命令git branch --set-upstream-to=...
原因是我使用了一个与多个远程仓库连接的分支,我想在更改之前检查分支是否已经与正确的上游连接。

4

4 回答 4

11

TL;DR:使用git rev-parse

$ git rev-parse --abbrev-ref master@{u}
weird/master

如果没有设置上游,你会得到:

fatal: no upstream configured for branch 'master'

(和一个非零退出代码)。/dev/null如果您不想要它,则将stderr 重定向到丢弃错误消息:

if master_upstream=$(git rev-parse --abbrev-ref master@{u} 2>/dev/null); then
    master_has_upstream=true
else
    master_has_upstream=false
fi

例如。

解释

Anthony Sottile 的回答 通常会为您提供正确的名称,但并非总是如此。特别要注意当remote.origin.fetch设置为origin不规范时会发生什么:

$ git init
Initialized empty Git repository in .../tmp/tt/.git/
$ git remote add origin git://github.com/git/git
$ git config remote.origin.fetch '+refs/heads/*:refs/remotes/weird/*'
$ git fetch
remote: Counting objects: 231294, done.
remote: Compressing objects: 100% (663/663), done.
remote: Total 231294 (delta 0), reused 662 (delta 0), pack-reused 230631
Receiving objects: 100% (231294/231294), 93.03 MiB | 3.54 MiB/s, done.
Resolving deltas: 100% (170261/170261), done.
From git://github.com/git/git
 * [new branch]          maint      -> weird/maint
 * [new branch]          master     -> weird/master
 * [new branch]          next       -> weird/next
 * [new branch]          pu         -> weird/pu
 * [new branch]          todo       -> weird/todo
 * [new tag]             v2.14.2    -> v2.14.2
[lots more tags snipped]

请注意,虽然远程被命名origin,但远程跟踪分支被命名为weird/master, weird/next,等等。它实际上有效:

$ git checkout master
Branch master set up to track remote branch master from origin.
Already on 'master'
$ git status
On branch master
Your branch is up-to-date with 'weird/master'.

nothing to commit, working tree clean

但是,.git/config如果远程跟踪分支名称为origin/master

[branch "master"]
    remote = origin
    merge = refs/heads/master

使用:

 branch="$(git branch | grep '\*' | cut -d' ' -f2-)"

工作得很好(尽管人们应该经常使用它git symbolic-ref --short HEAD来获取当前的分支名称:见下文)。

remote="$(git config "branch.${branch}.remote")"

这部分工作得很好——它得到了遥控器的名字。

remote_branch="$(git config "branch.${branch}.merge" | cut -d/ -f3-)"

这就是我们出错的地方。我们需要的是使用git rev-parseplus gitrevisions 语法来表示“指定分支的上游”,即附加@{u}或附加@{upstream}到分支名称。通常git rev-parse将其转换为哈希 ID,但是使用--abbrev-ref,它会打印名称的短版本,或者使用--symbolic-full-name,它会打印长版本:

$ git rev-parse --symbolic-full-name master@{u}
refs/remotes/weird/master

(我不知道为什么--abbrev-ref在一种情况下和--symbolic-full-name另一种情况下都拼写。)

请注意,使用git rev-parseon时HEAD,如果HEAD是分离的,则答案是符号HEAD。也就是说,在任何 Git 存储库中,git rev-parse HEAD总是成功,即使在打印符号名称时也是如此。但事实并非如此git symbolic-ref

$ git checkout --detach
HEAD is now at ea220ee40... The eleventh batch for 2.15
$ git rev-parse --abbrev-ref HEAD
HEAD
$ git rev-parse --symbolic-full-name HEAD
HEAD
$ git symbolic-ref HEAD
fatal: ref HEAD is not a symbolic ref

因此,为了解决HEAD(查找当前分支),请根据您在“无当前分支”情况下想要的行为选择要使用的命令。

于 2017-10-01T19:41:25.713 回答
2

以下是我git status以脚本友好的方式找到相同答案的方法:

 $ branch="$(git branch | grep '\*' | cut -d' ' -f2-)"
 $ remote="$(git config "branch.${branch}.remote")"
 $ remote_branch="$(git config "branch.${branch}.merge" | cut -d/ -f3-)"
 $ echo "${branch} is tracking ${remote}/${remote_branch}"
 print_locking_less is tracking origin/master

远程跟踪分支的信息存储在 中.git/config,如下所示:

[branch "print_locking_less"]
        remote = origin
        merge = refs/heads/master
于 2017-10-01T17:47:49.820 回答
0

事实上,我发现了使用命令的第一个技巧git status
我的分支是当前分支并且有一个上游,我得到一个类似的行Your branch is up-to-date with 'the_repo/the branch',但我宁愿有更直接的方法来知道这一点。

于 2017-10-01T17:24:02.660 回答
0

只需使用git branch -vv

foo    03b325f Commit on untracked branch
master b7da42b [origin/master] Initial commit

上游(如果有)很好地显示在方括号中。

手册摘录,重点补充:

-v
-vv
--verbose
在列表模式下,显示每个头部的 sha1 和提交主题行,以及与上游分支的关系(如果有)。 如果给出两次,则打印链接工作树的路径(如果有)和 上游分支的名称(另见 git remote show )。请注意,当前工作树的 HEAD 不会打印其路径(它将始终是您的当前目录)。

请注意,这比与 相同-vv的更详细。--verbose-v

于 2021-11-15T04:38:13.380 回答