The Conflict-Free Git Flow We Implemented at Kesia.id

The Conflict-Free Git Flow We Implemented at Kesia.id
Photo by Yancy Min / Unsplash

Hey folks! At Kesia.id, we were facing a classic development dilemma: How do we keep our codebase organized, support rapid feature releases, and minimize the dreaded merge conflicts that slow everyone down? We found our answer by adapting a well-known Git workflow to our specific needs.

nvie's Git Flow – A Solid Foundation

We started with nvie's Git Flow, a widely adopted model that uses dedicated branches for features, releases, and hotfixes.

The core idea is elegant:

  • master: Represents the stable, production-ready code.
  • develop: The main integration branch where all finished features converge before release.
  • feature branches: Created from develop, these are where individual features are built.
  • release branches: Forked from develop to prepare for a new release.
  • hotfix branches: Created from master to address urgent production issues.

The Challenge with nvie's Git Flow

nvie's Git Flow works beautifully when development timelines align perfectly with feature release cycles. However, at Kesia.id, we often need to cherry-pick features for immediate release, bypassing the standard release schedule. This led to:

  • Increased merge conflicts: Frequent cherry-picking caused our develop branch to diverge significantly from master, making merging a nightmare.
  • Slowed development: Resolving these conflicts took valuable time away from building new features.

Our Solution: A Tweak with Big Impact

To overcome this, we made a simple but impactful change to nvie's model:

We always branch features from master, not develop.

Here's how it works:

  1. Feature Branch: A developer creates a new feature branch directly from the latest commit on master. We keep these branches small and focused, with each branch addressing only one specific task or issue.
  2. Development: The feature is built on the branch.
  3. Rebase and Squash: Before creating a pull request, the developer must rebase their feature branch onto the latest master and squash all their commits into a single, clean commit. This ensures a linear project history and minimizes conflicts when merging.
  4. Pull Request to develop: When the feature is ready, a pull request is created to merge the feature into develop for integration testing.
  5. Merge to master: Once approved and tested, the feature branch is merged directly into master for immediate release (or included in the next scheduled release).

The Benefits We've Seen

  • Reduced Merge Conflicts: By branching from master and rebasing regularly, our feature branches stay much closer to the production code, drastically reducing conflicts.
  • Faster Feature Releases: Cherry-picking is no longer necessary, as features are already based on the latest master code.
  • Cleaner Development Process: The develop branch remains a cleaner staging area for integration testing before features are merged into master. The linear history due to squashing makes it easier to track changes and identify issues.

Key Considerations

While this modified Git Flow has been a game-changer for us, it might not be the perfect fit for every team. Consider your own release cycles, team size, and frequency of hotfixes before adopting this workflow.

Let me know if you'd like a more detailed walkthrough of our branching and merging strategies!

I hope this is helpful for your blog post! Feel free to ask if you have any other questions.

Subscribe to Ctrl+Alt+Run

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
[email protected]
Subscribe