The concepts of git-flow are elegant and simple, but the examples show only one repository. Using git-flow on a team is a little more complex. This post endeavors to describe the setup process and branching considerations when git-flow is used in a team environment.
If you’re the person who wants to bring git-flow into your team, this post is for you. Everyone else on the team needs these concepts of git-flow.
Converting an existing repository to git-flow
Note: if you have any branches lying around other than master, git flow init will not create the develop branch for you; it wants me to use one of these others. Either delete these branches or create the develop branch manually (git branch develop) before initializing git-flow.
Note: if these other guys have a branch lying around other than master, git flow will refuse to create the develop branch. Either delete these branches or create the develop branch manually (git branch develop origin/develop) before initializing git flow. The “origin/develop” at the end of that command sets up the tracking branch.
Multiple Branches + Multiple Team Members
Now that origin has two branches, and each team member is tracking both of them, there are a few other considerations.
Pull
If you’re used to using git pull, please stop. Please use git fetch. This downloads all the new stuff from origin without modifying your local branches or working directory. Decide which local branches you want to update; when you’re ready, rebase.
What used to be “git pull” becomes:
Fetch the updates from origin.
Observe whether we have changes.
Rebase to tack my changes on the end of the changes from origin.
Why rebase instead of merge? That’s a subject for a whole post (or a presentation! come see me at DevLINK), but the short answer is: non-fast-forward merge creates merge bubbles on the develop branch – evidence that development forked and a merge commit with no story to tell. The git-flow model is cleaner if merges are for features. This is my opinion.
Push
I recommend this magic spell:
git config push.default current
Run this once to tell git push that it should (by default) push only the current branch. This way, when you make commits on develop and push them to origin, you won’t be confused by error messages that occur because your master branch is behind.
Sharing branches
- make sure master, develop, and the release branch are all fully up-to-date in your local, because finishing the release will affect all three of these.
- git flow release finish versionName
- push both master and develop branches
- push the release tag to origin: git push origin versionName
- delete the release branch on origin: git push origin –delete release/versionName
so the publish word is the key. Now I'm trying to figure out how to see remote changes. Right know I'm doing git fetch & git status to see the changes. There's a way to do only git status and see remotes changes!?Thanks for the tips to working with a team.
I'm new to git, but if I understand your question correctly, you'd like to see how your local branch diverges from it's tracking branch on remote without a fetch?I use this: git diff –stat origin/develop
I would like to see a real-life git flow where release maintenance is factor in. A real-life case would be a re-release is not at the tip of development, but a hot-fix/fix from the release point.I understand the release can be created from the tags, but as soon as first 'fix' is needed for the release, then the release branch is going to need to be pushed to server. Something like libc or python managing version 2.7 and 2.8. A bug comes into 2.7, you aren't grabbing the tip of development, you are grabbing the last 2.7 release, fixing, and re-release 2.7 (bump version 2.7.x+1, tag …) AND I think pushing that release branch to server.Correct?
Great post. I'm converting a team from svn to git and this is exactly the missing piece that no one talks about.
Talk about late to the party…Try the –dry-run switch on fetch. It'll show you what it would do if you were actually fetch but not actually update any of your local pointers.