2

Basically i have a automated building script where i do a checkout of a local branch, and want to step to pull remote updates with git pull && git submodule update && make clean only if necessary, because otherwise i'd be wasting a lot of time when it was time to build.

I noticed that if had a local change going on and there are remote updates, or just remote updates, the output of git checkout in both cases would have a substring 'Your branch' (can be fast forwarded, or something similar), so i hacked that as my condition.

I'm uneasy about this.

Is there a reliable way to check that the remote has updates to pull and that can pulled without merge conflicts?

edit: what i currently have, inside a larger script is this:

OUTPUT=$( { git checkout "$NAME" ; } 2>&1 ) || { echo "Failed checking out branch" >&2; exit 1; }
[[ "$OUTPUT" == *"Your branch "* ]] && { git pull && git submodule update && make clean || { echo "Failed pulling, updating or cleaning branch" >&2; exit 1; }; }

1 Answer 1

3

You are going to need to get the information from the remote repo at some stage. At the moment you are using git pull to download the information and merge it. You should split this into 2 steps, first download the information of the state of the remote repo. As a second step see if you are up-to-date, if not then merge the data, do your make clean and make.

As git pull --help tells you, it runs git fetch and then either git rebase or git merge.

If you know the name of the local branch and the branch it is tracking, then you can use the low level command git show-ref to get the hash values and see if they are equal. This only works if you are exactly tracking an upstream branch but is very cheap.

same_commit(){
    set -- $(git show-ref --hash --verify "$@")
    [ "$1" = "$2" ]
}
# get the changes if any, but don't merge them yet
git fetch origin
# See if there are any changes
if same_commit mainline origin/mainline
then
   echo "Everything up to date"
   exit 0
fi
# Now merge the remote changes
git pull origin
make clean
make

If you have local changes as well then you need to see if your local branch has all of upstream.

contains(){
    # return true if the first name has the second as an ancestor
    git merge-base --is-ancestor "$2" "$1"
}
if contains master origin/master
then
    echo nothing to do
    return 0
fi
6
  • +1. It should be possible to automate the comparison, by checking whether the base branch (remote tracking branch, if there is one) contains HEAD, like git format-patch --base=auto does; but I don’t have the incantation handy. Nov 23, 2021 at 22:41
  • Is the the result of the second function a super-set of the first and it would also work if i had no changes to the local branch? Also i forgot to say it but i fetch externally in the second file here: gist.github.com/i30817/8ffcd35f7c16e4dbe474c5fb46a6a61e (navi is a bash helper that i'm using just to get the remote branches in a chooser list that works by querying the user for selections)
    – i30817
    Nov 24, 2021 at 21:50
  • Yes, the second function is a superset of the first, but much slower. For the first all git needs to do is read 2 short (41 byte) files (.git/refs/heads/master and .git/refs/heads/orign/master) and output them. I could have used bash builtins which would be faster still, but if something changes in the future about how git internals work then things might break. The second function needs to walk the chain of commit objects. Not very slow in absolute terms but still many times slower than the first. The second function does work if there are no local changes.
    – icarus
    Nov 24, 2021 at 23:47
  • Looks good, thanks.
    – i30817
    Nov 25, 2021 at 1:27
  • Ok, i have a problem here - i'm trying to use the 2nd function with a pull request branch from github made with git fetch origin "pull/<pr>/head:<pr>" - thing is these branches appear to have no set branch.upstream, and thus the function fails because i can't get a upstream name (with git status -b --porcelain=v2), much less a actual upstream. Is it even possible to track github upstreams from prs? All the tracking mechanisms seem to be for branches, which prs don't appear to be?
    – i30817
    Nov 25, 2021 at 3:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .