Search code examples
gitazure-devopscicd

What does it mean when one branch is ahead of another?


I am testing a scenario where devs create feature branches and push them into a dev branch (which is my compare branch). Once per week, we then merge dev into main, which triggers our CI/CD pipeline.

My intention was that main and dev should always match up. However, currently main is showing ahead of dev.

We don't work out of or push to our main branch, so how would it be ahead of our compare branch?

enter image description here


Solution

  • In Azure DevOps, there are 4 merge types to choose from:

    1. Merge (no fast forward): Merge with a non-linear history that preserves all commits.
    2. Squash commit: Merge with a linear history that combines all source commits into a single commit on the target, or squash merges the PR. Be aware that a new commit will be created for the target branch without keeping the commit history from the source branch.
    3. Rebase and fast-forward: Rebase the source commits onto the target and fast-forward.
    4. Semi-linear merge: Rebase source commits onto the target and create a two-parent merge.

    When your source branch is a shared branch, such as dev or main, (usually) the only sensible option to use is #1, "Merge", and in this case you will be creating a new merge commit on main when completing a Pull Request from dev into main.

    Given that, you have a few options that you can consider:

    1. If for some reason you really don't want to see the merge commit on main, you could theoretically avoid it by selecting merge type #3 (rebase and fast-forward). This is slightly dangerous though because if dev isn't fully up to date with main at the time of the merge, then dev will get re-rewritten. If it is fully up to date, it won't touch dev and you'll effectively do a merge with fast-forward (if possible, and it would by definition be possible).1
    2. Allow, the merge commit, and then immediately afterwards merge main back into dev with a regular merge. Now dev would be 1 commit ahead of main instead, but this is fine since the norm for your workflow is for dev to be ahead of main anyway. Note that if you ever have a hotfix into main, you'd need to also merge main back down to dev, so the rule here is something like "Anytime new commits appear on main, merge them back down into dev."
    3. You could setup a pipeline job that does the merge of dev into main for you. It could be setup to do a fast-forward merge into main, and then push it out when it's finished. (Assuming you've protected main, you'll also need to give the account that runs the pipeline permission to bypass pull requests.)

    1 In AzDO Server, I've seen semi-linear merge fail to even attempt a rebase when more than 25 commits would be rebased. It wouldn't surprise me if that's also true for rebase and fast-forward, however, someone should check whether the number of commits matters when a rebase isn't necessary. If you can't have more than 25 commits regardless of whether a rebase is necessary or not, then this may sometimes thwart the idea to do a fast-forward type merge by cheating with option 3.