Git Merge Strategies

Below are some options/strategies for merging Pull Requests (PRs) into a project's repository. Typically this will be into the project's master branch, but may also be a dev or feature branch. Please also note that a single project/repository may decide to use a variety of strategies based on the situation and context. For example "squash merge" PRs into a dev branch, and to a no-ff merge from dev to master. 

NOTE: this document is based off a discussion about merge options from June 3, 2020 (original Google Doc).

Merge --no-ff

Command: git merge <branch name> --no-ff --log 

See: git-merge

This uses the default git merge strategy and forces a merge commit which will contain a log of the individual commits. --no-ff  forces a merge commit, preventing a fast-forward commit. --log adds a log of the individual commit messages to the merge commit.

  • Pros
    • Retains all of the commit history from the branch being merged
    • Allows the contributor to decide what is included in the history
  • Cons
    • Retains all of the commit history from the branch being merged
      • Experimental work
      • Work in progress commits
      • Makes git history tools (e.g. blame) harder to understand.
        • e.g. It's possible that individual lines in a blame are from different commits, despite all being from work on a issue/task
    • Branching structure not visible in GitHub commits view; which shows commits linearly. This can be confusing when multiple issues are being worked on in parallel. When these are all merged together the individual commits from each branch will appear interwoven instead of chunked with related commits. 

Examples of when to use

  • When the project wants to retain all of the detailed history for the work involved

Squash Merge

Command: git merge --squash --log 

See: git-merge

Performs a merge by combining all of the commits to be merged into a single new commit. The merge commit will include a log of the individual commit logs from the squashed commits.

  • Pros
    • Combining all of the individual commits into a single commit makes viewing history cleaner/easier to read.
  • Cons
    • No explicit historical link between what's merged and the original commits from the branch
      • The squash commit log contains the individual commit logs, but no linked reference back to the original commits
      • May have more difficulty using git related tools and features
        • git won't be able to tell if your local branch has been merged with your Master branch
        • when building one branch from another branch
          • when merging the second branch it will include the commit logs that have already been merged from the previous squashed branch.
          • may have merge conflicts: for example thinking the same file was created in master and the second branch

Examples of when to use

  • When the project wants control over the presentation of the history in the repository
  • When cleaner history is prioritized over detailed work steps. (e.g. would prefer only the final contribution included and all related work combined together)

Rebase before merge

Command: git rebase master

See: git-rebase, Git Branching - Rebasing

In this case the onus is on the contributor to do the work; however, the project may require that a contributor rebase their work as the final step before a PR is merged into the repository. Rebasing allows for a contributor to clean up the presentation of commits, including potentially squashing commits together. 

NOTE: If the desire is only to combine a continuous sequence of commits  git commit --amend  or a form of git reset  may be used instead.

  • Pros
    • Provides a linear history that is cleaner/easier to read
    • No revision/history variance between the PR branch and project repository after merge
    • The contributor has control over what history/work is presented
  • Cons
    • Requires the contributor to do the work. Can be particularly confusing/difficult for new contributors to the project
    • Rewrites history
    • Potentially dangerous if other branches are dependent on the pre-rebased work in the brach
      • e.g. if work is being done in parallel that has branched off the PR branch prior to rebasing

Examples of when to use

  • When cleaner history is prioritized over detailed work steps.
  • When the contributor wants to curate/re-organize the presentation of their work