Your workflow seems similar to the “Git Flow”, except that you start feature branches from master
, whereas the Git Flow recommends branching from dev
.
The idea is that dev
closely reflects the current development state. Feature branches are supposed to be very short-lived (at most a couple of days of development). So when a feature is branched from dev
and merged back into dev
a day later, there will be very few conflicts. The dev
branch would be used for Continuous Integration.
Git Flow then suggest branching a release branch (your staging
) from the dev
branch with multiple new features for QA and release preparation. On release, the code is merged into master
so that master
only contains fully tested published versions.
If we were to branch new features off master
(i.e. the last published version), this would ignore all other features that have been merged into dev
in the meanwhile. Although the diff between dev^
and dev
might be rather clean, there would be vast differences in the history:
Am B..Zm
master ----x------------------------------------x
/ \ \ /
staging --x---|------------------|-------------x B..Zs
/As | B C..Y | Z /
dev x-----|---------x--x--x--|-----------x
A \ / / / | /
featureB x--x--x ..... | |
B1 B2 B3 | |
... | |
\ /
featureZ x--x--x
Z1 Z2 Z3
At merge B
into dev (A)
from featureB (A As Am B1 B2 B3)
, the merge is rather clean. We then add a couple of other features C
through Y
into dev
. After that, the history of dev
looks like A As Am B1 B2 B3 C1 C2 C3 ... Y1 Y2 Y3
. That still looks reasonable. Finally, we have the featureZ
branch with the history A As Am Z1 Z2 Z3
– note that Am
is the nearest common ancestor commit of dev
and featureZ
.
The result is that at merge Z
, we do not only test the effect of the commits Z1 Z2 Z3
, but the effect of combining all the features B1 B2 B3 C1 C2 ... Y2 Y3 Z1 Z2 Z3
.
The impact of this problem is reduced by frequent releases, so that the difference between dev
and master
is not that pronounced. However, this only makes the problem smaller, and does not solve it. TeamCity seems to realise that it's actually testing all the changes you made since you last merged into master, although these are not obvious in the branch history (since dev
only contains merge commits).
I recreated the above branching example as an actual git repo, which is available as latk/Git-Branching-Madness on GitHub. You can look at the branch graph online, or clone the repo and inspect it yourself, e.g.:
# tip: use "git log" with "--pretty=oneline"
$ git log featureZ # history of featureZ
$ git log dev^ # complete history of dev before featureZ merge
$ git log dev^..dev # what commits were added during the featureZ merge
$ git log master --graph # display complete branching history