Search code examples
gitgithubmergegit-flow

Managing changes from develop branch into feature prior to push (git)


Most of the teams I've worked on in the past have followed the same workflow when using Git (with some tiny variations):

  1. Pull the develop branch (git checkout develop)
  2. Create a new feature branch off of it (git checkout -b feature/XYZ-123)
  3. Do your work
  4. When you are ready to create a PR, add and commit your changes (git add . && git commit -m "some commit message"), then check develop back out, pull it (git checkout develop && git pull)
  5. Switch back over to your feature branch and merge develop into it (git checkout feature/XYZ-123 && git merge develop)
  6. Finally push (git push -u origin feature/XYZ-123) and create a PR

We'll call this the "Merge Method". The benefits are that any changes to develop since you created the branch are now merged into your branch. And so by the time you create a PR, there are no merge conflicts with develop and the code reviewers can see a clean, conflict-free diff between your branch and develop.

I am now working on a team that has a similar flow up until the merge step, but then instead of merging develop into my feature branch, they ask for a rebase from origin/develop. So the actual steps are:

  1. git checkout develop
  2. git checkout -b feature/XYZ-123
  3. Do your work
  4. git add . && git commit -m "some commit message"
  5. git checkout develop && git pull
  6. git checkout feature/XYZ-123
  7. Rebase from origin/dev
  8. git push -u origin feature/XYZ-123

We'll call this the "Rebase Method". It too produces merge conflict-free PRs, but obviously it must have different pros/cons from the Merge Method explained up above.

I'm wondering what those pros/cons are. What does the Merge Method lend itself to that the Rebase Method lacks, and vice versa? When should one method be used as opposed to the other?


Solution

  • but obviously it must have different pros/cons from the Merge Method explained up above

    Not really. Between reverse merging (as I call it) and rebasing, it's exactly the same effect in the end, namely to try to pick up all the most recent changes from develop so that (1) the feature branch can be tested accurately and (2) the chances of a merge conflict when merging into develop are reduced.

    The main visible difference between reverse merging and rebasing is the lack of the extra merge commit on the feature branch. That makes rebasing appealing. So:

    • Rebasing looks a lot cleaner in the history, because you appear to have started the branch from a much more recent state of develop.

    But here are some counterclaims:

    • If there's an incoming conflict, rebasing makes it harder to resolve those conflicts.

    • You can't rebase after pushing to form the pull request, because that rewrites shared history; whereas you can reverse merge at any time.

    Personally I use both! I rebase just before the initial push to form the pull request; if the pull request lives a long time, I reverse merge periodically, and especially just before the actual approval and merge.