Reputation: 4578
I am trying to maintain a bare copy of a Git repository and having some issues keeping the remote tracking branches up to date. I create the remote tracking branches like this:
git branch -t 0.1 origin/0.1
This seems to do what I need to do for that point in time. However, if I make changes to origin
and then fetch with the bare repo, things start to fall apart. My workflow looks like this:
git fetch origin
It looks like all of the commits come in at that point, but my local copy of 0.1 is not being updated. I can see that the changes have been brought into the repository by doing the following:
git diff 0.1 refs/remotes/origin/0.1
What do I need to do to get my tracking branch updated with the remote's updates? I feel like I must be missing a step or a flag somewhere.
Updated: Additional Clarification
Normally one would push into a bare repository, rather than run git fetch from within it. If you can arrange to do that, life will be much easier.
Here is a bit of clarification on the workflow.
The project's public git repository is hosted on GitHub. I am managing the project (wiki, issues, forums) using Redmine. Redmine requires a local bare repository in order to operate. When GitHub receives changes it pings Redmine. Redmine then attempts to fetch changes from its origin (GitHub).
This works great if I'm just working with master but it was not working with my tracking branches. The changes were being imported but were not being listed in the branch in Redmine repository browser because the local branches were not being updated.
I'm sure I could have worked this out another way but finding a (generic) solution to getting the tracking branches up and running was definitely my preference as most of the git related plugins for Redmine assume things like "git fetch origin" is all that needs to be done.
See accepted answer for the complete solution. The --mirror
solution seems to be exactly what is needed in this case.
Upvotes: 9
Views: 7097
Reputation: 467023
Normally one would push into a bare repository, rather than run git fetch
from within it. If you can arrange to do that, life will be much easier.
If you have to fetch rather than push, and you just want to create a mirror of origin in your bare repository, you could avoid having remote-tracking branches entirely. If you're starting this mirror from scratch, Charles Bailey points out below that git will do all of this setup for you if you initially clone the repository with git clone --mirror
.
Otherwise, you could get a similar effect with:
git fetch origin +refs/heads/*:refs/heads/*
The +
means that this will overwrite the state of your local branches with those from the remote. Without the +
, updates that aren't fast-forward merges will be rejected. However, if this is just a mirror, that shouldn't matter. (You can configure this to be the default action on git fetch origin
by setting the config variable remote.origin.fetch
to +refs/heads/*:refs/heads/*
. If you want to mirror tags and remote-tracking branches from origin as well, you could use +refs/*:refs/*
instead.)
However, if, as you originally ask, you want to maintain remote-tracking branches and selectively merge them into local branches, you can use the following steps, but I don't necessarily recommend them unless you're the only person using this bare repository. (Note: originally here I suggested using "git symbolic-ref HEAD refs/heads/whatever" to switch branch and "git reset --soft" to change the branch ref - however, Charles Bailey pointed out in the comments out that one can use "git update-ref refs/heads/whatever refs/remotes/origin/whatever", which doesn't require one to switch branch first.)
First, you might want to check that updating the branch would have been a fast-forward merge, and after that update the branch. Note that there is a race condition here, which is why I say you should only do this if you are the only person using your local bare repository - the check would be useless if someone else moves on the branch between those steps.
origin/master
includes master
) by comparing git merge-base master origin/master
with git show-ref master
- they should be the same. Or you could use the is-ancestor
script in this question, which does those commands with some additional checks.)master
in this case) to point to origin/master
with git update-ref refs/heads/master refs/remotes/origin/master
However, as I said at the beginning, I imagine that the real solution you want is either:
I hope that's of some use.
Upvotes: 18
Reputation: 11985
When you fetch
, remote changes are updating your own local reference for the remote, origin/0.1
(this never causes any conflicts, since origin/0.1
never hosts any local changes). To import those changes, you can git reset refs/remotes/origin/0.1
from 0.1
, which will make the HEAD branch (0.1
) point to the same commit as the remote branch.
Note that by doing so you will lose any changes to 0.1
not coming from the remote.
Upvotes: 1