如何读取 Git 分支的当前上游?

14

我正在寻找一个git命令来了解现有分支所关联的上游(如果有的话)。
(与“写”命令git branch --set-upstream-to=...相关的某种“读取”命令)
原因是我使用一个连接到几个远程仓库的分支,我想在更改它之前检查这个分支是否已经与正确的上游连接。

4个回答

14
TL;DR: 使用git rev-parse
$ git rev-parse --abbrev-ref master@{u}
weird/master

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

fatal: no upstream configured for branch 'master'

(以及非零的退出码)。如果不想看到错误消息,请将stderr重定向到/dev/null

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的回答通常可以得到正确的名称,但并非总是如此。特别是当originremote.origin.fetch设置不是标准设置时,请注意以下内容:

$ 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/masterweird/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

但是如果远程跟踪分支名称为origin/master.git/config文件中的内容仍然与预期相同:

[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-parse及gitrevisions语法,以确定指定分支的"上游(upstream)"。具体方式是,在分支名后附加@{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-parse 时,如果 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(查找当前分支),请选择要使用的命令,根据您在“没有当前分支”情况下想要的行为。


非常感谢,这非常清晰详细。就我而言,默认的远程仓库总是被称为origin,因此我将使用您的语法git rev-parse --abbrev-ref 'mybranch'@{upstream} - herve-guerin

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

这很好,但是非常棘手。我非常喜欢torek的解决方案!但是感谢提供关于文件.git/config的信息,这也很有趣。 - herve-guerin

1

只需使用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--verbose相同。


1
这应该是被接受的答案 :-) - undefined

0
实际上,我发现了一个使用git status命令的小技巧:
如果分支是当前分支并且有上游分支,我会得到一行类似于Your branch is up-to-date with 'the_repo/the branch'的信息,但我更希望有一种更直接的方式来知道这个信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接