The issue is that I need to look whether the branches which I want to merge are not published.
If they aren't published, you should rebase them.
But checking if a rebase is actually possible is a tiny bit tricky:
First, after fetching, you easily can check if you have local commits not yet pushed:
git log origin/master..master
o--o--o (origin/master)
/
x--x--x--y--y (master)
It is perfectly ok to rebase in this instance, except if master was already pushed to another branch from your repo.
But you also can check that easily with:
git branch -r --contains master
If any remote (-r) branch contains the branch you want to rebase, then it is a less safe idea, and a merge is preferable.
But, if the remote branch itself was rebased (and forced pushed), then you need to be careful, as detailed in "How do you deal with a public repository that has already been rebased?":
o--o--o (OLD origin/master)
/
x--x--X--y--y (master)
\
o'--o'--o' (origin/master, as seen after a 'git fetch')
Rebasing blindly master on top of origin/master would replay commit X, which was left out when origin/master was rebased. Not good.
Today (January 2014), the only way to deal with this case is to:
- make a 'tmp' marker branch on
origin/master,
git fetch,
- check if
git branch --contain tmp lists origin/master (which has been fetched and is possibly with a different history if it was rebased and forced pushed).
Tomorrow (git 1.9, Q1 2014), you won't have to mark your remote branch before fetching:
fork_point=$(git merge-base --fork-point origin/upstreamBranch yourBranch)
# return X
git rebase --onto origin/upstreamBranch $fork_point yourBranch
To recap:
After a git fetch (after marking origin/master before the fetch),
- if
git log origin/master..master returns commits from master which aren't part of origin/master (meaning those local commits haven't been pushed to origin/master)
- AND if
git branch -r --contains master is empty (meaning master wasn't pushed anywhere else, on any remote tracking branch you can see through a git fetch)
Then:
- if
origin/master include the marker branch 'tmp' (meaning origin/master itself wasn't rebased), you can git rebase origin/master master.
- else: you can
git rebase --onto origin/master $(git merge-base tmp master) master
(you need tmp here to rebase just your branch. Git 1.9 will make the need for a tmp branch needless)
In any other cases: merge origin/master to master.