tags:

views:

92

answers:

4

How to check whether the remote repo has changed and I need to pull?

Now I use this simple script:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

but it is rather heavy.

Do you know any better way? The ideal solution would check all the remote branches, and return names of the changed branches and the number of new commits in each one.

+2  A: 

The command

git ls-remote origin -h refs/heads/master

will list the current head on the remote -- you can compare it to a previous value or see if you have the SHA in your local repo.

brool
Any sample script to compare these values?
takeshin
+1  A: 

I think the best way to do this would be:

git diff remotes/origin/HEAD

Assuming that you have the this refspec registered. You should if you have cloned the repository, otherwise (i.e., if the repo was created de novo locally, and pushed to the remote), you need to add the refspec explicitly.

Jeet
+4  A: 

git remote update to bring your remote refs up to date. Then you can do one of several things, such as:

  1. git status -uno will tell you whether the branch you are tracking is ahead, behind or has diverged. If it says nothing, the local and remote are the same.

  2. git show-branch *master will show you the commits in all of the branches whose names end in master (eg master and origin/master).

If you use -v with git remote update you can see which branches got updated, so you don't really need any further commands.

However, it looks like you want to do this in a script or program and end up with a true/false value. If so, there are ways to check the relationship between your current HEAD commit and the head of the branch you are tracking, although since there are four possible outcomes you can't reduce it to a yes/no answer. However, if you're prepared to do a pull --rebase then you can treat "local is behind" and "local has diverged" as "need to pull", and the other two as "don't need to pull".

You can get the commit id of any ref using git rev-list --max-count=1 <ref>, so you can do this for master and origin/master and compare them. If they are equal, the branches are the same. If they're unequal, you want to know which is ahead of the other. Using git merge-base master origin/master will tell you the common ancestor of both branches, and if they haven't diverged this will be the same as one or the other. If you get three different ids, the branches have diverged.

To do this properly, eg in a script, you would need to get the name of the current branch, and the name of the remote branch it's tracking. Check out the bash prompt-setting function in /etc/bash_completion.d for ideas.

Neil Mayhew
@takeshin I guess you could combine git ls-remote origin -h refs/heads/master as suggested by @brool with git rev-list --max-count=1 origin/master. If they return the same hash, the remote branch hasn't changed since you last updated your remote refs (with pull, fetch, remote update, etc.) This would have the advantage that you wouldn't have to pull down the content of all the commits right away, but could leave that for a more convenient time. However, since remote update is non-destructive, you might as well do it anyway.
Neil Mayhew
+2  A: 

Run git fetch (remote) to update your remote refs, it's show you what's new. Then, when you checkout your local branch, it will show you whether it's behind upstream.

che
I think he already has the local branch checked out, so he needs something else to show whether it's behind etc. He can do this with git status.
Neil Mayhew
True, after you've fetched remotes, `git status` will show that as well.
che
That's something in the mood `git pull --dry-run` does, but I think it is to heavy for a cron script run each minute.
takeshin
@takeshin: You can't check remote repositories without going on the network. If there isn't anything new `fetch`'s not going to do much beyond than checking status. If you need a very fast and lightweight reaction on remote updates, you might want to look into hooking some kind of notifications to the remote repository.
che
@takeshin: if you're wanting to check the remote repo every minute I think you've missed the point of DVCS. The whole idea is to be able to develop independently for a while, and then put it all together smoothly later. It's not like cvs, svn, p4 etc. where you always have to be working on top of whatever is the latest in the repository. If you really need something that somebody else is working on, then you should use a different communication mechanism, such as email, to tell you when it's ready to pull.
Neil Mayhew
@takeshin: As @che says, use the post-receive hook on the remote repo to call contrib/hooks/post-receive-email and configure this to send to a mailing list for the repo. Developers who use the remote repo can then subscribe to this list.
Neil Mayhew