My question is similar to this one.
I pushed a local branch to a server, creating it for the first time on that server and setting it as the local branch's upstream with --upstream
. I am having trouble extracting tracking information programatically from the upstream without making unecessary changes to the local git repository. For example, I would like to know the commit hash that the HEAD
of the upstream is pointing to.
Here's how I created that remote branch and set as upstream:
$ git push --set-upstream sshname:/user/project.git
I can git pull
, git push
etc. just fine. However, I have a script in my .bashrc
that inspects the hash of the latest commit on the upstream server and compares it with my current branche's hash. (This is used to prettify the prompt with a colorscheme that help me quickly see whether I remembered to push a repo to the server, or whether I'm on a detached head, etc). The script works fine on most local repositories, where it gets that remote HEAD
hash with
$ git rev-parse "$(git branch --show-current 2> /dev/null)"@{upstream}
> fatal: upstream branch 'refs/heads/master' not stored as a remote-tracking branch
As you see, it fails with the claim that there the branch on the remote is not stored locally as a remote tracking branch.
I looked for various suggestions on StackExchange on how to get around this, including How to create git Remote-Tracking Branch and learning Git: tracking vs. setting upstream (-u) for remotes?. Nothing helps. Many of the suggestions are just wrong, with people conflating remotes
, remote tracking branches
and upstream urls
.
Here is the output of various commands that people might suggest:
$ git remote -vv
> [no output]
$ git branch -vva
> * master <HASH> <COMMIT_MSG>
$ git fetch -a
> From sshname:/user/project
* branch master -> FETCH_HEAD
This is the first one that shows the information I'm looking for. But it's not in a machine-parseable format and there's no --porcelain
. It's also wrong. The real URL ends in .git
. And the server does actually need this .git
suffix; it cannot be ignored.
$ git ls-remote
> From sshname:/user/project.git
<HASH> HEAD
<HASH> refs/heads/master
The correct URL now, but again not machine-parseable.
I can also run 'destructive' operations (not OK for scripting) in order to fetch this information indirectly in a similar fashion:
$ git pull
> From sshname:/user/project
* branch master -> FETCH_HEAD
Already up to date.
Wrong URL again.
$ git push
> Pushing to sshname:/user/project.git
To gitea:/murdock/dupmaster.git
= [up to date] master -> master
Everything up-to-date
Needless to say, I can hardly trust such inconsistent output for scripts. I need a porcelain
-like output.
Now the closest solution I found was:
$ git config -l
> ...
branch.master.remote=sshname:/user/project.git
branch.master.merge=refs/heads/master
Indicating that I could get the upstream 'URL' this way:
$ git config --get branch.master.remote
> sshname:/user/project.git
But still, I cannot probe the remote tracking information. Manually, I could add a git remote based on this 'URL' and then run git fetch -a
and that (probably) would resolve my issue. But this is a 'destructive' process which alters the git
repo. I'm trying to script something which doesn't make unecessary changes to the repos.
How can I programatically fetch tracking information in a reliable way, without altering the git repo?
I would settle for automatically creating remote tracking branches, if that were possible. But I do not want to create remotes (how would I name them automatically? etc).