gitgithubpull-requestbranching-and-merging

Git branching strategy for maintaining a stable release while continuing product development


I am working on a web application project. Our objective is to upgrade an existing application by adding new pages and functionality.

We have completed the first phase of the project that upgraded the part of their application currently in use.

At this point we have two branches.

  1. main: where all the future development is being done (unstable version)
  2. production-branch: where the current version of the site is kept (stable version)

My goal is to keep a stable branch that we can seldom use for bug fixes and minor features. And use the main branch to continue development. I would like to be able to move fast and break things, deploying to our testing environment, while keeping a stable version available at any point for bug fixes.

The problem is:

The question is:


Solution

  • How do I merge production-branch to main without contaminating the production-branch? (with code from main)

    There are many ways to achieve this. (In fact most ways would normally achieve this.) From the comments we've learned that you didn't realize you used a reverse merge of main into production-branch so that you can resolve conflicts.

    Before you begin, since my recommendations are local operations, use git fetch to make sure all of your remote branches are up to date. Also delete your local copies of main and production-branch to ensure you're working with the latest versions from the remote. (And this assumes you don't care about any local commits you may have added to those branches and never pushed.) The below options assume you have already fetched and don't have out-of-date local copies of these branches.

    Here are some options to properly merge production-branch into main:

    Option 1: Merge directly to main and push it

    git switch main
    git merge production-branch
    # resolve conflicts and stage the files
    git merge --continue
    # Modify the commit message as needed
    git push
    

    Note the git push in the last line. There are 2 possible reasons that that push of main could fail:

    1. You may not have permission to directly push commits to main. In this case you (or an admin) can temporarily give you the permission to push, and after you push, you can remove that permission.
    2. If it took you a while to resolve the conflicts or if you are simply unlucky, maybe someone else added new commits on main since when you last fetched. If this happened then you won't be able to push, and of course you don't want to force push a shared branch either. So now you could either fetch again and start over, or, you could go use option 2 below by creating a temp branch based off of your current main which has the merge in it, and then push it out and create a PR.

    Option 2: Create a temporary branch so you can use a PR

    # create a temporary branch pointing to main, but don't track main
    git switch -c merge-production-branch-into-main origin/main --no-track
    git merge production-branch
    # resolve conflicts and stage the files
    git merge --continue
    # Modify the commit message as needed
    git push origin merge-production-branch-into-main
    # Now create a PR from merge-production-branch-into-main into main
    

    With this PR method, make sure you use a regular merge when completing the PR. (Do not squash or rebase!) In theory, if it were available, you could also fast-forward but only if you merged in the correct direction as described above. With the regular merge you will actually be adding 2 new merge commits to main; one for the conflict-resolution merge, and one for the PR merge. This is completely fine.

    Since you are using a temp branch with a PR, if you complete the PR with a regular merge, then the direction you do the temp branch conflict-resolution merge actually doesn't matter. The way I described above is probably slightly better, however, the reverse merge that you did actually would work in this case as well, but only if you do it on a temp branch and merge that temp branch into main with a new merge commit. The exception to this, as mentioned in the previous paragraph, is even on a temp branch, you do not want to do the reverse merge if you are going to then fast-forward this branch back into main. The reason is that will flip the first-parent history which leads to pain and suffering for all.