"fetch --all" in a git bare repository doesn't synchronize local branches to the remote ones
I'm trying to synchronize periodically a git bare repository, my local branches are created using the "--track" option. here is my config (without unnecessary things):
[core]
bare = true
[remote "origin"]
url = [email protected]:Ummon/D-LAN.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "website"]
remote = origin
merge = refs/heads/website
I must use the 'cp' command to update the local branches:
git fetch --all
cp -r refs/remotes/origin/* refs/heads
Is there a more elegant solution?
Instead of copying the ref files around (bad bad!) use git update-ref
Note that you can have what you wanted pretty easily to a bare repository when pushing instead of pulling.
Use this:
git clone --mirror . /tmp/bareclone
to create the bare repository that you want to keep completely in synch Now, to synch all the branches to the bareclone mirror, use
git push /tmp/bareclone --mirror
NOTE that this will also remove any heads that aren't in the source repo but (still) are in the bareclone. Also note that you can use send-pack instead of push there because this interface is rather lowlevel and actually implemented by send-pack
HTH
As the commenter noted, I slighly avoided the subject that it doesn't seem possible at once to do the inverse. However, you can get a long ways towards the goal by doing something slightly advanced like:
1. Simple, safe and pretty unexciting.
git fetch $url -- $(git ls-remote -h $url |
while read sha ref; do echo "$ref:refs/remotes/fetched/${ref#refs/heads/}"; done)
Set `url=git://your.server/project.git' e.g.
I made sure that the refs are created in a moderately safe location. The effect very similar to doing.
git remote add fetched $url --fetch
So there is nothing much, but it shows you how to use plumbing commands to achieve it, so we can now adapt them to our needs:
2. Fetch directly into local branches (heads)
Now if you are sure you know what you're doing you can use the following style to get the branches duplicated locally:
git init --bare .
git fetch $url -- $(git ls-remote -h $url |
while read sha ref; do echo "$ref:$ref"; done)
Note: if you want to force update (e.g. when there is no fast-forward pull because of an upstream rebase, reset, filter-branch, or amended commit (in general -- any rewritten history) replace
echo "$ref:$ref"
byecho "+$ref:$ref"
; (Thanks Dov)
3. The full monty
This could also be combined, so you can have a remote definition too. I'd recommend that because it will mean that the local branches are actually tracking the ones from the remotes, and you'll have better insulation/recovery options if you accidentally clobber some of the local commits on these branches with these powerful fetch commands
git init --bare .
git remote add fetched $url --fetch
git for-each-ref --format='%(refname:short)' -- 'refs/remotes/fetched/' |
while read ref; do git branch -t "$(basename "$ref")" "$ref"; done
Have fun, HTH