GitLab CEO here. I agree that GitFlow is needlessly complex and that there should be one main branch. The author advises to merge in feature branches by rebasing them on master. I think that it is harmful to rewrite history. You will lose cherry-picks, references in issues and testing results (CI) of those commits if you give them a new identifier.<p>The power of git is the ability to work in parallel without getting in each-others way. No longer having a linear history is an acceptable consequence. In reality the history was never linear to begin with. It is better to have a messy but realistic history if you want to trace back what happend and who did and tested what at what time. I prefer my code to be clean and my history to be correct.<p>I prefer to start with GitHub flow (merging feature branches without rebasing) and described how to deal with different environments and release branches in GitLab Flow <a href="https://about.gitlab.com/2014/09/29/gitlab-flow/" rel="nofollow">https://about.gitlab.com/2014/09/29/gitlab-flow/</a>
> ...the history of a project managed using GitFlow for some time invariably starts to resemble a giant ball of spaghetti. Try to find out how the project progressed from something like this...<p>It's simple. Read backwards down the `develop` branch and read off the `feature/whatever` branches. Just because the graph isn't "pretty" doesn't mean it's useless.<p>In general, I'm starting to dislike "XXX considered harmful" articles. It seems to me like you can spout any opinion under a title of that format and generate lingering doubt, even if the article itself doesn't hold water. Not to generalize, of course--not all "XXX considered harmful" articles are harmful. They generally make at least some good points. I just think the title format feels kind of clickbaity at this point.<p>That said, kudos to the author for suggesting an alternative rather than just enumerating the shortcomings of GitFlow.
The approach discussed on the article seems to take into account only one possibility: you deploy master in prod, and it's always considered correct.
That works for small projects, but in my experience, when you have a bunch of people (let's say 20) pushing code to a repo, you need several levels of "correctness"<p>- branches: Work in progress.<p>- develop: Code ready to share with others. It can break the build (merge conflicts, etc) and it won't be the end of the world.<p>- master: This shouldn't be broken. It needs to point to a commit that has already been proven not break the build/pass all the required tests.<p>As always, you need to find a balance with these things and adapt to the peculiarities of your code base and team. I really see them as suggestions...
I have never understood why people hate merge commits so much. Their advantages are not insignificant: you know when a feature got merged in master, its much easier to revert a feature if you have a merge commit for it, much easier to generate a change log with merge commits, and you have none of the problems that pushing "cleaned up" histories will have: <a href="https://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html" rel="nofollow">https://www.mail-archive.com/dri-devel@lists.sourceforge.net...</a><p>The main disadvantage, as the article rightly points out, is that it makes it much harder to read the history. But that's easily solved with a simple switch: --no-merges. It works with git-log, gitk, tig, and probably others too. Use --no-merges, and get a nice looking linear history without those pesky merge commits.
You don't need to implement ALL of gitflow - I see it as scalable.<p>Master should always be latest production code, development branch contains all code pre-release. That's the core.<p>The other branches let you scale gitflow - if you need to track upcoming release bugfixes etc, you can use a release branch. A team of maybe 6 or 7 would likely start to need a release branch. Feature branches at this point are best left local on the developers repository. They rebase to fixup commits, and then merge those into develop when they're ready.<p>If you get into bigger teams - like maybe 6 agile teams working on different larger features, then you can introduce feature branches for the teams to use on sprints to keep the work separate.<p>The issue with gitflow is the lack of continuous integration, so I personally like to get teams to work only on a develop branch during sprints and use feature toggles to commit work to the develop branch without breaking anything.<p>As I see it, gitflow and CI are at odds and that's my biggest gripe with integrating lots of feature branching for teams - everyone has to integrate at the end of the day.<p>So I believe the model can and should be scaled back as far as possible, using only develop and master and release as primary workflow branches, introducing the others when the need arises - doing it just because it says so in the doc isn't the right approach.
Anyone else fed up of articles using "considered harmful" in the title? Especially when it's just that the author doesn't like that thing.
So let me get this straight.<p>He is suggesting to use 90% of what GitFlow suggests (feature/hotfix/release branches) but doesn't like the suggestion of non-fast-forward merge and master/Dev and that makes GitFlow harmful? I don't think I agree.<p>I think having the Dev branch is useful. Consider this actual scenario at my current workplace.<p>1. We have 4 developers. Nature of the project is such that we can all work independently on different features/changes.<p>2. We have Production/QA/Dev environment.<p>3. When we are working on our individual features, we do the work in individual branches and merge in to Dev branch (which is continuously deployed).This lets us know of potential code conflicts between developers in advance.<p>4. When a particular feature is 'developer tested', he/she merges it into a rolling release branch (Release-1.1, Release-1.2 etc) and this is continuously deployed to QA environment. Business user does their testing in QA environment and provides sign off.<p>5. We deploy the artifacts of the signed off release branch to Production and then merge it in to the master and tag it.<p>Without the development branch, the only place to find out code conflicts will be in the release branch. I and others on my team personally prefer the early feedback we can get thanks to the development branch.<p>Advantages of an explicit merge commit:<p>1. Creating the merge commit makes it trivial to revert your merge. [Yes, I know it is possible to revert the merge but it's not exactly a one step process.]<p>2. Being able to visually see that set of commits belongs to a feature branch. This is more important to me (and my team) than a 'linear history' that the author loves.<p>We have diverted from GitFlow in only one way, we create all feature/release/bugfix branches from 'master' and not 'develop'.<p>Now, don't get me wrong, GitFlow is not simple but it's not as complicated as author seems to suggest. I think the author was better served with article title like 'What I don't like in GitFlow'.
A reason that we are switching from full git flow to a reduced model (basically one master branch + feature branches, occasional hotfix branches) is that git flow isn't compatible with continuous integration and continuous delivery.<p>The idea of CI is that you integrate all commits, so you must integrate the develop branch - build the software, run the tests, deploy it to a production-like environment, test it there too.<p>So naturally, most testing happens in that environment; and then you make a production release starting from the master branch, and then install that -- and it's not the same binary that you tested before.<p>Sure, you could have two test/staging environments, but I don't think I could get anybody to test their features in both environments. That's just not practical.
Do what is easiest for you.<p>1. Merging vs Rebasing<p>Open source projects should stick with Merging over cherry-picking and rebasing especially if you want others to contribute. Unless you feel fine doing all of the rebasing and cherry-picking for them. Otherwise, good luck gathering a large enough pool of people to contribute. Simplicity always wins here.<p>2. GitFlow vs X<p>Once again do what is good for your company and the people around you. If you have a lot of developers having multiple branches is actually /beneficial/ as Master is considered ALWAYS working. Develop branch contains things that are ready to ship, and only things that are READY TO SHIP. So if your feature isn't ready yet, it can't go to develop, and it won't hit master. Your features are done in other branches.<p>3. Rewriting history<p>Never do this. Seriously, it will come to bite you in the ass.<p>4. Have fun.<p>Arguing is for people who don't get shit done.
> I thought it was a weird, over-engineered solution to a non-existent problem.<p>To be fair, its a cookie-cutter approach that resonates with people unfamiliar with git but not ready/willing to invest the time to understand it deeply. That is understandable; a lot of people come from other systems and just need to get going right away and gits poor reputation for command-line consistency etc. is well-earned.<p>(To be clear, I am not a fan of git flow.)<p>If anyone is interested in truly understanding git, start here: <a href="http://ftp.newartisans.com/pub/git.from.bottom.up.pdf" rel="nofollow">http://ftp.newartisans.com/pub/git.from.bottom.up.pdf</a>
The only thing GitFlow had going for it is that it has a clearly written article about it with pictures that explain how it works. That's it; the freedom of git and being able to define what works for you is too much for people and they think they need to turn development back into Subversion-style or desktop-release style.
GitFlow is also in my opinion a bad flow as it does end up with a merge commit spaghetti over time.<p>Merge commits are great. They are here to group a list of commits into a logical set. This logical set could represent one "feature", but not necessarily. It is up to you to decide whether commits A B C D should or shouldn't be grouped by a merge commit. Merge commits also make regression searchs (i.e. git bisect) a lot faster. And to top it of, they will make your history extremely readable, but that is granted you merge correctly... and that is where git rebase and git merge --no-ff come into play.<p>At my company, every developer must rebase their topical branch on top of the master branch before merging. Once the topical branch is rebased, the merge is done with a --no-ff. With this extremely easy flow, you end up with a linear history, made of a master branch going straight up and only everyonce in a while a merge commit.<p>Our commit history looks like this:<p><pre><code> *-------------*---------*---------*----------*----*------->
\-----------/ \---------/ \--/
</code></pre>
Following the simple rule "commit, commit, commit..., rebase, merge --no-ff" avoided the merge spaghetti a lot of people compain about. Although, I have to admit our repository is small (6583 commits to date).<p>This works even when multiple devs work on the same branch: they must get in touch on a regular basis, rebase the branch they are working on and force push it. Rewritting history of topical branches is only bad if it is not agreed on. As long as it is done in a controlled manner nothing's wrong with it.<p>Another rule we follow is to always "git pull --rebase" (or git config branch.autosetuprebase=true).<p>Our approach might not, however, scale for larger teams or open source projects.
I have had this ideological debate about "fast forwarding" more times that I can count. I agree with the author "no-ff" is silly. I've been working on professional software teams for over a decade. When I encountered fast forwarding/rebasing it was absolutely a breath of fresh air. I've been using git now for 5 years and I have not encountered a single instance where using either of these tools has presented any sort of problem. I can't remember a week where having a concise, readable history hasn't proven its value. I also can't remember a single time I've said "Man I'm glad I had all these merge commits around they really saved my proverbial bacon"<p>From what I can tell no-ff exists to satisfy the aesthetic preference of your local team pedant. It gives them something to do between harping on whether your behavior is in the correct "domain", deciding if a list comprehensions are truly "pythonic", and spending that extra month perfecting the event sourcing engine to revolutionize the "contact us" section of your site.
I can distill my thoughts down to this:<p>The time it takes to carefully rebase a branch onto another, and to compress commits for a feature into one, is still much longer than the time it takes for my eyes to pass over so-called "empty" merge commits.<p>If I want to look at when a feature entered a branch, I can look at its merge commit. And the feature branches are there to show how a feature was built; bugs could be the result of a design decision that happened in one of the midway commits.<p>I looked at OP's example pic in the blog, and I read all of his words, but I wasn't sold. His picture looks like a normal git history to me. It requires almost no effort to find what I'm looking for.<p>And that's not even touching his rage against the idea of a canonical release branch (master). But that's for another day.
I actually thought GitHub Flow was more commonly used, as it's lighter-weight:<p>[1] <a href="http://scottchacon.com/2011/08/31/github-flow.html" rel="nofollow">http://scottchacon.com/2011/08/31/github-flow.html</a><p>[2] <a href="https://guides.github.com/introduction/flow/" rel="nofollow">https://guides.github.com/introduction/flow/</a>
I second the feeling of GitFlow being over-engineering: <a href="http://blog.talles.me/that-git-flow.html" rel="nofollow">http://blog.talles.me/that-git-flow.html</a>
It's not confusing, maybe it's not suited for your particular case, as any other tool. There's no magic tool/process/etc that does it all for everybody.<p>GitFlow has been working great for us. A team of 15 developers, working with feature branches, we have our CircleCI configured to automatically deploy the "develop" branch to our "QA environment", and our "master" branch to "production" environment.<p>The "hotfix" and "release" are proven to be useful to us too; we just need to have effective communication with our team, so everybody rebase their feature branch after a merge in our main branches.
I have come to actually like the two permanent branches approach. I know that for any repository that follows this model that:<p>* "master" is the current stable release<p>* "develop" is the current "mostly stable" development version<p>The first time you clone a repository this is an extremely helpful convention to quickly get your head around the state of things.<p>If you're doing it right (and don't use --no-ff, which I agree is unreasonable), I can't think of a scenario where this causes extra merge commits. Merges to master should <i>always</i> be fast forward merges.
Advising rebasing over explicit merges is dangerous and foolish. Rebasing does have its place, but you really need to know what you're doing.<p>Also, I don't see his point about that messy history. I can see exactly what happened in that history (though the branch names could have been more informative). With multiple people working on the same project, feature branches will save your sanity when you need to do a release, and one feature turns out to not be ready.
Git-flow indeed has serious problems. This author is proposing a particular subset of gitworkflows(7).<p><a href="https://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html" rel="nofollow">https://www.kernel.org/pub/software/scm/git/docs/gitworkflow...</a><p>I like subsetting gitworkflows(7) because you can incrementally add process when the tangible benefits (like increased reliability and experimental access for eager users) outweigh their process cost (which depends on team experience). I wrote about these issues here:<p><a href="http://mail-archive.com/search?l=mid&q=87zjx4x417.fsf@mcs.anl.gov" rel="nofollow">http://mail-archive.com/search?l=mid&q=87zjx4x417.fsf@mcs.an...</a><p>This diagram represents a workflow that uses 'maint', 'master', and 'next' branches.<p><a href="http://59A2.org/files/simplified-gitworkflows7.svg" rel="nofollow">http://59A2.org/files/simplified-gitworkflows7.svg</a>
To me (a mercurial user mostly) this is kind of like a "no duh" article having never read the original "gitflow."<p>I think that is because I am used to using hg's branches, bookmarks, and tags for different use cases.<p>If I want to mark a revision as a particular release number (which is something we don't really do here but I can see the value) then I would use hg tag. Tag's are permanent.<p>If I want to mark a revision as "production" and then have some automated process take over based on the the updated info, I would use hg bookmark. Bookmarks are the closest equivalent to git's branches. Bookmarks can be updated to a new revision or removed.<p>If I wanted to work on a parallel branch of development for an experimental feature or if I am attempting to upgrade some dependencies, I can use hg branch. This creates a named branch in the code base which is permanent. This branch can eventually be either closed or merged back into the main.
It seems like one of the ironies of git-flow is that it would actually work better if you used it with Mercurial rather than Git, because Mercurial stores what branch you were on when you made a commit. This means that a tool could automatically look at the Mercurial commit tree and figure out which swimlane each commit belongs in, and use this information to draw a commit history tree that wasn't such a mess.<p>I apologize for the self-promotion, but this answer on Stack Overflow (and the question) talks about this difference between Git and Mercurial, and includes links to articles that explain it better than I could:<p><a href="http://stackoverflow.com/a/26784550/1013442" rel="nofollow">http://stackoverflow.com/a/26784550/1013442</a>
Posted a link to this prior blog of mine in article comments also - <a href="http://michaeldehaan.net/post/116465000577/understanding-when-to-use-git-rebase" rel="nofollow">http://michaeldehaan.net/post/116465000577/understanding-whe...</a> - but I'm a huge fan of rebase and topic branches.<p>One main branch is great, and also if working with a large number of contributors I really like a clean history, and makes things much easier to review.<p>It's kind of a shame something got branded with a slick name like "GitFlow", when "doing it the way you ought to be doing it" doesn't have a slick name :)
A single eternal master works for a Continuously Deployed app/site.<p>Not for <i>any</i> other project where maintenance releases are a norm. This includes stuff strict API compatibility projects, semantically versioned frameworks/plugins/libraries, many forms of desktop/offline apps, some android apps, most enterprise apps, etc - more or less where developers don't have the liberty to thrust the latest master on their users.<p>I'm not against CD, and not a big fan of Git Flow either. But different things have their own uses. I'm really liking GitHub Flow and GitLab Flow though!
> All other branches (feature, release, hotfix, and whatever else you need) are temporary and only used as a convenience to share code with other developers and as a backup measure. They are always removed once the changes present on them land on master.<p>From an open source developer's perspective I need more "eternal" branches because I need to plan future releases. Putting everything into master makes the decision for me (if I have a breaking change I have to bump a major version even if maybe I want to delay doing that).
I wish GitFlow had not called that branch "master", and had called it "released" or "production" instead. It's really useful to have a branch which you know always exactly represents the code running in production. You can keep an IDE pointed at somewhere and update when you need to without worrying about tags or whatever. This is the one part of it I've tried to sell to colleagues, which would have been easier if it had a better name.
I think he makes a valid point about how it's not necessary to have both develop and master if you use tags. On the other hand, I think the `--no-ff` merges is what git-flow got right. The separation of features into their own branches is useful. It's basically about grouping related commits together. You can always render the history in a way that looks prettier and even if you can't--the history doesn't need to look pretty, the final product does.
I don't see why there has to be "this is harmful" and "this is a better way".<p>I've used all kinds of branching models... I've used just a master branch and you commit directly to master. I've used full git-flow.<p>I think the branching model you use is dependent on the people and the project. But really no matter which model I've used it seemed to me to be fine... And if it wasn't fine, we extended it to meet our requirements.
Most of the merges in his first pictures aren't even fast-forwardable, so his complaint about no-ff seems.. weird?<p>You should still rebase your feature branch on top of whatever you're merging into whenever you can, even if you're using git-flow. That's just common sense. When you do, your history looks almost the same as in his 'pretty graph', there's just one more 'link' back to the previous feature merge.<p>The advantages of this additional context are important. Firstly, you can get a compressed view of only the features that were merged (without detailed commits) with something like `git log --first-parent`. I guess the only way to do that in OPs approach is `git log | grep 'SPA-'`? Rather... unreliable.<p>Using no-ff also means you don't have to do the silly thing of putting your issue name / branch name in every commit title. Titles are pretty short already, having to allocate ~10% of it to tracking the name of the branch is just wasteful. With no-ff it's obvious which feature the commit is for (the branch name in the merge). If your tool fails to present that in a reasonable fashion, that's disappointing, but the data includes this context and that's the most important thing.<p>As to the master/develop split, yeah I could be convinced it's unnecessary. Still, I think it's convenient to have a clear separation of 'this code is in production', 'this code is in development'. If you just make a release branch then merge it into develop, you have to know the exact tag before being able to find the latest release. 'master' being the alias for 'latest release' is fine.
We use a more extreme version of rebasing feature branches before merging into master: we squash the features into a single commit when merging to master. The reason is that we don't care about the (sometimes hundreds of) commits that made up a feature. What matters is that it works as designed and passes tests. If we merge a feature to master and then need to revert it, we will revert the whole feature.<p>This also allows us to keep merging master into feature branches, (where there is only a single commit that might need to be manually merged) instead of rebasing feature branches on master (in which case it can be necessary to manually merge multiple intermediate commits).<p>What cleared up git merge --squash for me was a comment showing that:<p><pre><code> git checkout master
git merge --squash feature
</code></pre>
is the equivalent of doing:<p><pre><code> git checkout feature
git diff master > feature.patch
git checkout master
patch -p1 < feature.patch
git add .</code></pre>
I see GitFlow as a pragmatic workflow customized to cloud-based software. Master is auto-deployed, and Dev acts as insurance.<p>We're currently having lots of success with this:<p>* Always work in a feature branch.
* Pull master + rebase feature branch when done.
* Merge to master with --no-ff --edit and include a summary.<p>Rebasing feature branches keeps them readable and avoids continuous merges. Disable fast-forward keeps the log for /master abstracted to feature-level, but the details are available in the graph.<p>Major releases are branched, minors (bugfixes) are tagged. Bugfixes are made in master and cherry-picked into the release where possible.<p>Currently our CI build only works on /master, but in the coming month it'll build all feature branches which have been pushed to the main repository.<p>This is very similar to how Perforce streams work, but it's distributed. If you really hate distributed version control and love GUIs then I can recommend Perforce.
That's the first time I heard of GitFlow. People seriously do software development this way? I find that hard to believe.<p>What the author describes is fairly close to what I've been using in a number of companies now for the last 9 years or so.<p>Whether to rebase is a personal preference. I tell developers to always rebase local work before committing. Unobserved changes might as well not exist (if a tree falls in the forest and no one is there to hear it falling, does it make a sound?), so if you haven't pushed your work, rebase it. No one cares <i>when</i> you did the work.<p>As for feature branches, it depends. If the history is clean and there aren't too many at one time, we might merge without rebasing. But I still prefer to clean up the commit history and rebase. I don't understand the obsession with "true history". History is written by victors, in this case — resulting work/code.
The whole point of hotfixes is that they are relative to <i>old</i> code and that they <i>alter what is considered the current version of that old release</i>. Which is important when (as is typical in business) you have customers who are on specific releases and either haven't paid for the new hotness, or haven't integrated to it and don't yet want it.<p>So absolute minimum you need one persistent branch per old release, if you ever hotfixed it and still have it deployed in the field. GitFlow falls over here, because it only has one master. But at least it does recognize the fact that repairing released code is different from pushing the unreleased state of the art forward.
I can count on zero hands the number of times I've needed to solve a problem by navigating the branch tree.<p>I've lost count of the number of times that two eternal branches and feature branches with pull requests (+ code review) has saved major flaws from getting to production.<p>The develop branch is perfect for automatically deploying our bleeding edge to our test server.<p>Although, if we move to a more continuous deployment approach, we may transition away from two eternal branches. But when GitFlow was first written about, continuous deployment really wasn't the trend that it is now.<p>Methods will continue to evolve...
I never used gitflow so I could be wrong but the main problem with logging seems to be this:<p>Gitflow thinks about branches as lanes. Git branches are actually labels. What's the difference? In the gitflow model <i>every</i> commit belongs (implicitly) to a branch (or a lane). Git branches don't work that way. One could actually implement "lane" as an additional commit metadata and tweak git-log (and other git utilities) to always show lanes in straight lines in the graph.
On the main project I'm working on, the reason we have develop/master is mainly for hotfixes.<p>We deploy once a week, but if we need to get something out the door quickly, we make a hotfix branch off of master, then merge it into both develop <i>and</i> master. This way, if we find something that needs to be fixed before the next release, but don't want to push half-done updates, we can seamlessly do it.
One thing that bothers me about GitFlow is that it mangles history with merges. Sometimes it becomes tricky to debug issues when history was created with GitFlow.<p>I would rather branch off of master, bring changes in via git am or rebasing when ready, then tag a release when it is ready to be released. If there is something wrong with master, the tagged releases serve as easy points to branch off of.
I think it greatly depends of the size of your team: if you're alone you have one branch, if you're two you may have 3 branches, each for one of you + master, if you're four you start to use feature-based branches..<p>It might be fun to compute the number of branches needed as a function of the number of devs in your team.
Ever since I started getting involved in SCCM stuff, I've been astounded at how much breath and emotion people are eager to waste defending their choice, or technique or strategy or whathaveyou.<p>SCCM system discussions should be banned on HN, as pointless and heated as vi vs. EMACS discussions.
It's not really harmful just because it's too much overhead for small projects. If you have a huge project I'd assume that it's much harder to read history anyway, and then a more complex pattern of development is reasonable.
Even though I could frequently commit on feature branches, I usually don't. Hence, when I merge feature branches I don't have crazy messy histories that I feel it necessary to rewrite.... Works for me.
What about using merging when it comes to the feature branches but rebase when pulling (git pull --rebase)? Is it that harmful to rewrite the history for your local changes?
I personally find git flow to be a wonderfully elegant and simple way of handling a project in git. Not everything is perfect, but I consider git flow to be much like PEP8. It's almost always a good idea to do it the git flow way, unless you have a very specific and documented exception, in which case do that instead.<p>To me what matters more is the consistency.<p>Also, the attitude and tone of this article straight up stinks.