Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Which merge strategy do you recommend?

    # Merge commit
    git merge --no-ff -m <message> <hash>
    # Squash and merge
    git merge --no-commit --squash <hash>
    git commit -m <message>
    # Rebase and merge
    git rebase --force-rebase <hash>
From https://stackoverflow.com/a/52301456


I...have to admit that my merge strategy, and what I teach my teams, is "don't" :) (only slightly tongue-in-cheek)

I believe in clean, linear history, and strongly prefer rebase-based workflows to merges. That's actually one of the reasons I chose Phabricator for my current place, as it is also very opinionated towards the same way of working.

Edit: oh, and to answer your actual question, the third one.


+1. Interactive rebase to squash your feature branch, then ff merge into master/mainline.

Years ago when I was just reading about git instead of using it, I saw sentiments along the lines of "always use feature branches and merge them so your thoughts and process can still be looked at later". In the last ~5 years or so I've worked professionally, I've not once wished I could reference intermediate commits in my own code or someone else's. I've found that ambiguities and clarifications can and are caught during the code review process.

I'd say another couple of benefits:

- It's relatively easy to teach git workflows when the log/graph is linear, and similarly it's _way_ easier to reason about your workspace when you have an actual production codebase.

- Merge commits can make certain operations like reverts and patches harder to reason about


> In the last ~5 years or so I've worked professionally, I've not once wished I could reference intermediate commits in my own code or someone else's. I've found that ambiguities and clarifications can and are caught during the code review process.

One command I often use is git blame which allows me to find the commit that's associated with a particular line of code. Then I can look at the commit message and the diff against its parent. Perhaps what I'm changing may undo a bugfix and I wouldn't have realized it without reading the associated commit message.


That's separate from what the grandparent talked about. During the process of developing a new feature, I may incrementally refactor old code a few times, but only some of those changes make it into the final merge.

When I look back at the history, I'm only interested in seeing the changes that actually made it through, not every intermediate alley and dead end in between. If those dead ends are significant discoveries/results, I document them elsewhere.


Yes, that's exactly my main motivation for rebasing too: properly thought-out commits can give more context to the lines of code I'm looking at. (I wrote these thoughts up in more detail here: https://vincenttunru.com/Spend-effort-on-your-Git-commits )


The trick is you have to pick one of "merge always and avoid rebase" or "rebase always and avoid merging". If you take a branch, merge master into it, do some more development and then rebase it onto master, you are asking for trouble. If you have a revert in there (and especially a revert on a merge commit), it's a world of hurt.

But either way works fine. It just gives you a different history. My team likes merging because they don't understand exactly what happens when rebasing. In that environment `git log --topo-order` is practically a necessity, though.


I prefer to say, merges should only flow one way. (And always rebase before a merge.)

If you are merging master into a feature branch that has ongoing work and continues without merging back to master, that's the problem.

If your feature branch is short-lived, it can be easily rebased.

If your other branch is more like a release branch, with lots of work that can't be rebased easily, some times you can't really avoid a merge from master without communicating it first. If your team is large or distributed it might not be practical to say "release has moved to (rebased ref), please catch up"

In that case you should treat merges to release the same as merges to master (they should be finished bits of work that are considered published) and any unmerged features for the release, are kept on feature branches that are based on the release. They can be rebased after the point where master is merged back into release to avoid the nasty merge conflicts.


When cleaning up my own feature branch for review

    git merge —-squash <tree-ish>
When merging into the baseline

    git merge —-no-ff <tree-ish>
The reason for the latter is subtle. Yes, a perfectly linear history is nice in the aesthetic sense. However, the merge commits are artifacts of reviews that are useful in process audits, which QA and QC like to preserve.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: