-
Notifications
You must be signed in to change notification settings - Fork 1
Multiple remote repositories
- Create a new commit in Alice's clone:
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ vi LICENSE
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git add LICENSE
ben@GregoryHouse:~/tmp/testRepo-clone (experimental +)$ git commit -m "Add licence"
[experimental c95e129] Add licence
1 file changed, 1 insertion(+)
create mode 100644 LICENSE
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git status
# On branch experimental
# Your branch is ahead of 'origin/experimental' by 1 commit.
#
nothing to commit (working directory clean)-
As you can see we are no more in sync with the remote branch, but ahead of it.
-
Warning: here we could try to push it directly to our remote repository, on the same branch, but we can't. (see at the bottom of the page for an explanation). This situation is a bit particular, and does not correspond to a git usual workflow. You rarely push to somebody else's repository (see Git Workflows). Rather you pull from somebody else's.
-
If you trust each other and want to put in common your work on the same repos, you will then create a third repository, a bare repository. A bare repository stores branches but doesn't checks them out.
ben@GregoryHouse:~/tmp/testRepo-bare (master)$ cd ..
ben@GregoryHouse:~/tmp$ rm -rf testRepo-bare/
ben@GregoryHouse:~/tmp$ git clone --bare testRepo testRepo-bare.git
Cloning into bare repository 'testRepo-bare.git'...
done.
ben@GregoryHouse:~/tmp$ ls testRepo-bare.git/
branches config description HEAD hooks info objects packed-refs refs
ben@GregoryHouse:~/tmp$ ls testRepo/.git
branches config gitk.cache hooks info objects refs
COMMIT_EDITMSG description HEAD index logs ORIG_HEAD- Do you see the differences between a bare and non-bare repo? All the control files and the database of objects usually located in a hidden directory .git are at the root level of the repository, and you can't checkout a branch (you may try to convince yourself).
- The convention is to name such bare repos with a .git suffix in their name.
- Each local repository can keep track of several remotes.
ben@GregoryHouse:~/tmp$ cd testRepo-clone/
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git remote
origin
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git remote add sharedRepo ../testRepo-bare.git/
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git remote
origin
sharedRepo
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git remote show sharedRepo
* remote sharedRepo
Fetch URL: ../testRepo-bare.git/
Push URL: ../testRepo-bare.git/
HEAD branch: master
Remote branches:
alternateHistory new (next fetch will store in remotes/sharedRepo)
experimental new (next fetch will store in remotes/sharedRepo)
master new (next fetch will store in remotes/sharedRepo)
Local ref configured for 'git push':
experimental pushes to experimental (fast-forwardable)- We have added a new remote location. Note this sentence:
Local ref configured for 'git push': experimental pushes to experimental (fast-forwardable)
Git knows how to pair branches of the same name, and this time we can push towards this repo without any problems, it is not checked out, and we are ahead of it, so any push will be fast forward. It means there will be no conflict. Let's check that:
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git fetch sharedRepo
From ../testRepo-bare
* [new branch] alternateHistory -> sharedRepo/alternateHistory
* [new branch] experimental -> sharedRepo/experimental
* [new branch] master -> sharedRepo/master
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git branch -av
* experimental c95e129 [ahead 1] Add licence
remotes/origin/HEAD -> origin/experimental
remotes/origin/alternateHistory 4a9deba First commit: add README
remotes/origin/experimental c3df0e6 improvement
remotes/origin/master c6c5566 Add .gitignore, add a line to README
remotes/sharedRepo/alternateHistory 4a9deba First commit: add README
remotes/sharedRepo/experimental c3df0e6 improvement
remotes/sharedRepo/master c6c5566 Add .gitignore, add a line to README- All that's left to us is to push to this new remote location!
Jump to Push Commits
- Of course you can always rename, delete, etc remote.
git remote --helpis your friend. Not much exciting here.
####Optional explanation on why you usually don't push to non-bare repositories.
- Let's try it.
ben@GregoryHouse:~/tmp/testRepo-clone (experimental)$ git push origin
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 339 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
remote: error: refusing to update checked out branch: refs/heads/experimental
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To /home/ben/tmp/testRepo
! [remote rejected] experimental -> experimental (branch is currently checked out)
error: failed to push some refs to '/home/ben/tmp/testRepo'The error is a bit complicated, but it says everything you need to know. As already explained, branches can be considered as pointers to the HEAD of the commit tree. And running git checkout creates a so called working tree from the HEAD. While we tried to push this new commit, the result would have been a HEAD that would differ from the current view the user has when he edits the files. Resetting his view would be the only way to be back in sync with the HEAD of the tree. This is dangerous, and cannot be done automatically, because the remote user may be working on his working tree at that time, and have uncommitted files that would be forgotten by a reset. You may force the push and try it if you want to fool around a little.