Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How read the current upstream for a git branch

I'm searching a git command to know the upstream associated with an existing branch (if any).
(some kind of "read" command associated with the "write" command git branch --set-upstream-to=...)
The reason is I use a branch connected with several remote repos, and I'd like to check if the branch is already connected with the right upstream before changing it.

like image 348
herve-guerin Avatar asked Oct 01 '17 17:10

herve-guerin


People also ask

How do I view upstream in git?

You can check tracking branches by running the “git branch” command with the “-vv” option. We can set the upstream branch using the “git push” command. $ git push -u origin branch Total 0 (delta 0), reused 0 (delta 0) * [new branch] branch -> branch Branch 'branch' set up to track remote branch 'branch' from 'origin'.

How do I fetch a branch in upstream?

just need to run git fetch , which will retrieve all branches and updates, and after that, run git checkout <branch> which will create a local copy of the branch because all branches are already loaded in your system.

What is git branch upstream?

What is Git Upstream Branch? When you want to checkout a branch in git from a remote repository such as GitHub or Bitbucket, the “Upstream Branch” is the remote branch hosted on Github or Bitbucket. It's the branch you fetch/pull from whenever you issue a plain git fetch/git pull basically without arguments.

How can I tell which remote branch I am tracking?

There is a command that gives you about all tracking branches. And to know about the pull and push configuration per branch you can use the command git remote show origin. and you can use -sb option for seeing the upstream. Hope this information will help you to find which branch is tracking.

How do I set the upstream branch in Git?

The easiest way to set the upstream branch is to use the “ git push ” command with the “-u” option for upstream branch. Alternatively, you can use the “ –set-upstream ” option that is equivalent to the “-u” option.

How to sync upstream repository in Git?

To sync an upstream repo, first, you need to fetch the upstream changes. Then, merge the changes from the upstream branch to the local branch. In this example, its the main upstream branch. But when we talk about an upstream branch, it refers to the specific upstream of a branch in the remote respository.

What happens when you send something upstream in Git?

When you send something upstream, you are sending it back to the original authors of the repository. With git set upstream, you can choose where your current local branch will flow. It allows you to change the default remote branch. How to Set Upstream Branch in Git

How do I set the upstream branch of a Test Branch?

The test branch now has a set upstream branch. Instead of going through these commands every time you create a new branch, set up a short alias command. You can modify your existing Git commands or create a bash command. 1. Configure the global alias command through git config with the --global command:


2 Answers

Here's how I found the same answer as git status but in a script-friendly way:

 $ 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

The information for remote tracking branch is stored in .git/config, it looks like this:

[branch "print_locking_less"]
        remote = origin
        merge = refs/heads/master
like image 59
Anthony Sottile Avatar answered Oct 13 '22 01:10

Anthony Sottile


TL;DR: use git rev-parse

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

If no upstream is set, you get:

fatal: no upstream configured for branch 'master'

(and a nonzero exit code). Redirect stderr to /dev/null to discard the error message if you don't want it:

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

for instance.

Explanation

Anthony Sottile's answer usually gets you the correct name, but not quite always. In particular, watch what happens when the remote.origin.fetch setting for origin is not the norm:

$ 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]

Note that while the remote is named origin, the remote-tracking branches are named weird/master, weird/next, and so on. And it actually works:

$ 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

But what's in .git/config still looks like you would expect if the remote-tracking branch name were origin/master:

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

Using:

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

works well enough (although one should often use git symbolic-ref --short HEAD to get the current branch name: see below).

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

This part works perfectly—it gets the name of the remote.

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

This is where we go wrong. What we need is to use git rev-parse plus the gitrevisions syntax for "the upstream of a specified branch", which is to append @{u} or @{upstream} to the branch name. Normally git rev-parse turns this into a hash ID, but with --abbrev-ref, it prints a short version of the name, or with --symbolic-full-name, it prints the long version:

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

(I have no idea why this is spelled --abbrev-ref in one case and --symbolic-full-name in another.)

Note that when using git rev-parse on HEAD, if HEAD is detached, the answer is the symbol HEAD. That is, in any Git repository, git rev-parse HEAD always succeeds, even when printing symbolic names. This is not true for git symbolic-ref though:

$ 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

So for resolving HEAD (to find the current branch), choose which command to use based on the behavior you want in the "no current branch" case.

like image 38
torek Avatar answered Oct 13 '22 01:10

torek