I'm following the the workflow described here, as I found many references pointing to this page as a good workflow. As mentioned in the article, "feature" branches are shared between developers, but do not go to the central repository.
Let's say a developer "A" starts a new feature branch with git checkout -b newfeature develop
. Now let's say that developer "B" needs also to work on this feature. This is my problem.
What I did:
- developer "B" adds developer A's machine as a remote
- developer "B" runs
git branch remoteA/newfeature
- developer "B" works on this branch, commit his work and pushes the changes back to remoteA.
Step 3 is not working, right now. I get a message:
remote: error: By default, updating the current branch in a non-bare
repository is denied, because it will make the index and work tree
inconsistent with what you pushed, and will require 'git reset --hard'
to match the work tree to HEAD.
remote: error: You can set 'receive.denyCurrentBranch' configuration
variable to 'ignore' or 'warn' in the remote repository to allow
pushing into its current branch; however, this is not recommended
unless you arranged to update its work tree to match what you pushed
in some other way.
remote: error: To squelch this message and still keep the default
behaviour, set receive.denyCurrentBranch' configuration variable to
'refuse'.
I have already set sharedRepository = true
, but it did not help.
I have 2 questions:
- what's the correct way to share feature branches between developers?
- how can I push back the changes in developer B's repository to developer A's original one?
You can push to a non-bare repo. What you cannot do is push to a non-bare repo that has the branch that you are pushing to checked out. The reason for this should make sense. Changing the files that someone else is possibly working on would be incorrect.
Typically you will want to push to master or some other common shared branch. In order to avoid this conflict, the owner of the remote non-bare repo should work on a local branch or at least some other branch. Then you can push to the shared branch.
To use your example:
- developer "B" adds developer A's machine as a remote
- developer "B" runs
git branch remoteA/newfeature
- developer "A" does work on a local branch.
git checkout -b work-newfeature
- developer "B" works on this branch, commit his work and pushes the changes back to remoteA.
- Developer "A" rebases to get the new work:
git rebase newfeature
The easiest way to share feature branches is to simply push them to the central repository so anyone can pull from them. That way you can simply use the infrastructure you already have for your main repository and you can easily share code.
Once a feature branch on the remote is no longer needed you can simply delete it by doing a
git push <server> :branch
I'd advise against sharing directly between developer machines as that is prone to problems like users being on different networks (not connected to each other).
If possible you can also use the GitHub model where there is one central repository on the server (the blessed main repo).
And besides that main repository each developer has a "fork" of that repository where he has full commit access and can push branches to his liking.
In this case you can add your coworkers forks as remotes to your repository while maintaining easy access to the one centralized server (saving you the hassle of setting up SSH keys on every machine etc etc)..
A description on the GitHub model can be found here:
http://www.eqqon.com/index.php/Collaborative_Github_Workflow
Update: As a commentor pointed out this is a good link to get started with the centralized-feature-branch workflow: http://nvie.com/posts/a-successful-git-branching-model/
Update2: To expand on your second question:
What you are trying to do is push to a non-bare repository of another developer.
Git introduced in some previous version (I think 1.6 or so) the concept of a bare repository - that's a repository that has no checked out state but only contains the database that normally goes into .git
.
The reasoning behind this change was that whenever you push to your fellow co-workers repository (who is currently working on something) - you are manipulating the repository right under his nose. So he checks out version featureA-1 .. starts work .. you then push featureA-2 onto his repo and when he wants to commit he runs into trouble because the branch he was in has advanced by one commit he didn't see during development.
Because this is quite disruptive - Most people have adopted the notion of local git repositories (the ones where you actively do work on) should be private while you have a public git-repo (the fork) where you receive and share changes. That way you will never be interrupted by anyone else during your work (that's the whole idea behind the decentralized model anyway) and can only incorporate changes you want to have. (Nobody can push something onto your current work).