Reputation: 25623
I have two pc's where I have stored my repos. They are not connect via any kind of network! Lets name the repos on that two different pc's repo1 and repo2.
And I have a local "clone" which can I move from one to the other pc. Lets name this cloned repository as simply the "clone".
If I now fetch my clone from the origin ( which is here repo1), everything is fine. But if I need to use the repo2, I can't get it to run!
Simply the command
git fetch --all repo2
gives me: fetch --all does not take a repository argument
At this point I have no idea how to continue.
I found a lot of worarounds like: How to clone all remote branches in Git?
But none of the answers dealing with multiple repos!
Is that simply not manageable?
Upvotes: 3
Views: 2729
Reputation: 14743
First, I'd suggest to check the URL of your repos at stake by doing git remote -v
. For the sequel, I assume that you have two remotes named origin
and repo2
.
Regarding the SO question you mention - How to clone all remote branches in Git? - it should be noted that it is unneeded to checkout all branches to retrieve them, because git fetch repo2
is enough to get locally the whole history of remote repo2
.
According to the doc of git fetch, you can also do git fetch --all
(with no additional argument) instead of git fetch origin ; git fetch repo2
.
I recall that in order to list the remote branches corresponding to the remote called repo2
, you can just do git branch -r
which will show something like:
origin/HEAD -> origin/master
origin/master
origin/name-of-an-origin-branch
...
repo2/HEAD -> repo2/master
repo2/master
repo2/name-of-a-repo2-branch
...
that is, all remote branches are prefixed with the identifier of the remote.
In order to browse the content of these remote branches (without requiring some internet connection), you can either do gitk --all
to display a read-only summary of the history of all branches, or git checkout name-of-a-repo2-branch
to create a local branch associated to the tracking branch name-of-a-repo2-branch
(see the doc of git checkout).
Or you can do the usual git manipulations such as merge (e.g. git merge origin/master
), rebase (e.g., git rebase repo2/master
) involving tracking branches from your remote repos.
Regarding your main use case (synchronize two repos that are not directly connected by a network, using a "local moveable clone"), I think the simplest configuration would be to have a "bare" moveable intermediate repo (i.e., a repo with no working directory, see the corresponding doc) at a given local URL, say "file:///path/to/bare-repo.git".
To setup one such repo, you could just do:
git init --bare /path/to/bare-repo.git
Then in repo1 you could do the following setup:
git remote add sync file:///path/to/bare-repo.git
git config alias.pull-ff-sync '!f(){ git fetch sync && git for-each-ref --format "%(refname:strip=3)" refs/remotes/sync/ | grep -v -e '\''^HEAD$'\'' | xargs -n1 bash -c '\''git checkout -q "$1" && git pull --ff-only -v sync "$1"'\'' bash; }; f'
git config alias.pull-ff-sync # to check the alias has been properly setup
# and in particular that the «'\''» have been replaced with single «'»
git config push.default matching
for b in master develop ... ; do git push sync ${b}; done
# push all the branches you want to sync
And of course, a similar setup in repo2:
git remote add sync file:///path/that/can/be/different/to/bare-repo.git
git config alias.pull-ff-sync '!f(){ git fetch sync && git for-each-ref --format "%(refname:strip=3)" refs/remotes/sync/ | grep -v -e '\''^HEAD$'\'' | xargs -n1 bash -c '\''git checkout -q "$1" && git pull --ff-only -v sync "$1"'\'' bash; }; f'
git config push.default matching
Now, in repo1 (resp. in repo2), you can sync in the following way:
to fetch all the branches you have selected and merge them if the operation is fast-forward (so this command is more powerful than just git fetch sync
because all local branches will be updated if a manual merge commit is not required):
git pull-ff-sync
to push all the branches you have selected (which relies on the matching
setting of the push.default configuration):
git push -v sync
Note that if you don't want to change the push.default
config of your two repos (e.g., if you also want to use git push
to only push one branch from repo1 to another remote...), you can instead:
replace
git config push.default matching
with
git config push.default upstream # recommended
or just with
git config push.default simple # the default config in Git >= 2.0
run the slightly longer command below to send all matching branches from repo1 (resp. repo2) to the sync remote in one go:
git push -v sync :
Upvotes: 3
Reputation: 2654
ErikMD's two origin answer is the right way.
However, if you don't care about force pushing the repo, i.e, you have run (git pull --all
or git fetch -all
) and are sure that the other pc will not commit anything during the time you are doing this, then:
git push --mirror
From the docs:
--mirror
Instead of naming each ref to push, specifies that all refs under refs/ (which includes but is not limited to refs/heads/, refs/remotes/, and refs/tags/) be mirrored to the remote repository. Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remoate end, and deleted refs will be removed from the remote end. This is the default if the configuration option remote..mirror is set.
Another way to fix all
option is to try this answer.
Upvotes: 0