For years I work with Perforce and unfortunately didn't work with Git a lot, except for a few hobby projects, so please excuse my unknowingness.

In Perforce I use a ring integrate concept like outlined below.

Developers work in branch feature1v,feature2 and feature3. They integrate into the dev branch. The dev branch only goes to stable if all machines compile it successfully. That means that every developer who integrates from stable to feature1,feature2 or feature3 has always a working base to integrate from.

|      ^
|      |
|      |
|    dev <---+---+
|            |   |
|            |   |
+--->feature1+   |
|                |
|                |

Question, does that concept make sense in git and is that even possible with a DAG? Or how would you structure the branch structure in Git?


It should be possible and I believe is somewhat common. What you've drawn is only a ring in terms of how you maintain it, but doesn't actually introduce any cycles in the commit DAG because the branch names (especially 'stable') are moving targets, whereas the commit DAG uses exact parent IDs.

That is, 'feature1' isn't recorded as based on 'stable', it is based on the specific commit that was tip of 'stable' at that point in time. Once you merge 'feature1' into 'dev' and from there to 'stable', this does not retroactively update the base of all feature branches, they retain the same DAG as they had before.

And likewise, merging a branch just integrates the commits from that point in time and doesn't get retroactively updated. So you can safely back-merge 'stable' into 'feature1' during development, and this won't affect the future merge of 'future1' into 'dev'/'stable'. (I see it occasionally done in linux.git but I believe they try to avoid it, because it does generate an ugly-looking DAG.)

Instead of back-merging, you also have the option to manually rebase the feature branch to integrate new work from 'stable'. Though this (like any rewrite) creates new commits on top of the new base, discarding those which are already present in the base. (So rebasing a freshly-merged branch will result in an empty branch.)

It is still impossible to introduce cycles that way because each commit's ID depends on its parent (e.g. if there's A←B, it is outright impossible to rewrite A to get B←A without invalidating the existing pointer that B already has; all you'd get is A←B←A' and not a cycle).

  • Thanks so much for the detailed explanation l! That helped a lot. I will take a look into rebasing. Maybe that does the job too – Daniel Stephens May 16 at 12:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.