1

I've been working on getting my team's git workflow down and succinct. Our team uses master,staging, and development branches for our build servers.

When a new task/feature is being worked on, we will begin by creating our feature branch from master, commit it forward as many times as needed, then use a temp branch to squash it all down to 1 commit and move it to either staging or development.

Consider this basic diagram:

Master
   |
Staging
   | 
Development ——> [F1] ——> [F2]
   |
*Temporary* ——> [F2] 
   |
Feature1 ——> [A ——> B ——> C] = [F1]
   |
Feature2 ——> [A ——> B ——> C] = [F2]

Here, we see the starting place of all branches lines up. The commits for each feature are isolated and kept together. When the feature is moved upstream, the feature's commits are squashed, then merged into the upstream branch. For example, moving a feature to development would mean:

    git checkout development;            # Switch to Development
    git pull --rebase $DEV_REMOTE;       # Rebase changes onto development
    git checkout $MASTER;                # Switch to master branch
    git checkout -b $SQUASH;             # So that we can clone a squash branch from it
    git merge --squash $FEATURE_BRANCH;  # Merge in the feature
    git commit -m "Testing ($FEATURE_BRANCH)"; # Meaningfully Commit
    git rebase $DEV_LOCAL;               # Rebase Local Dev onto Feature
    git checkout $DEV_LOCAL;             # Switch back to Dev
    git merge $SQUASH;                   # Merge on the feature
    git branch -D $SQUASH;               # Delete Squash Branch

This was working quite well for a short while until I came upon my first conflict while squashing. I'm not sure where the change was made and why git cannot automatically use history to resolve it. It's a very basic in/out swap.

My question is: is there a better way to be doing this? We want to merge our code into both dev/staging with 1 commit per feature branch, without destroying/dirtying the feature branch when testing on development (rebasing unapproved code from dev into feature branch will include those changes when merging into staging branch).

Neurax
  • 3,657
  • 2
  • 13
  • 18

1 Answers1

0

I will suggest you to cherry pick the merged commit from master branch to staging and development branch separately.

Assume the commit history at first as below:

        D----E---F    feature
       /
...---A---B---C   master
...---G---H---I   development
...---J---K---L   staging

The commands used as below:

git checkout master
git merge feature --squash
git checkout development
git cherry-pick master
git checkout staging
git cherry-pick master
git branch -D feature

Then the commit history will be (commit M is the squash merged commit from feature branch, commit M' is the cherry-pick commit from master branch, commit M'' is the commit also cherry-pick from master branch):

...---A---B---C---M     master
...---G---H---I---M'    development
...---J---K---L---M''   staging

This will make your main branches master, development and staging work as separate linear structure.

Note: Whether there has conflicts when squash merging, it's depend on what you changed on feature branch and master branch. But no matter for squash merge or cherry-pick, you can use -X option to resolve the conflicts automatically. -X ours will resolve the conflict files by keeping the version as the current branch. -X theirs will resolve the conflict files by keeping the version as the other side.

Besides, if you need to record the relations among the three main branches, you can merge them together: squash merge feature into master -> merge master into development -> merge development into staging branch -> delete feature branch. Then the commit history will be:

...---A---B---C---M         master
                   \
  ...---G---H---I---M'      development
                     \
    ...---J---K---L---M''   staging
Marina Liu
  • 36,876
  • 5
  • 61
  • 74