Skip to content

Instantly share code, notes, and snippets.

@lcobucci
Last active June 3, 2020 23:37
Show Gist options
  • Save lcobucci/ebb450bc3f7b93b3dc1a1a62e0df2186 to your computer and use it in GitHub Desktop.
Save lcobucci/ebb450bc3f7b93b3dc1a1a62e0df2186 to your computer and use it in GitHub Desktop.
Branching model proposal (diagrams created using https://github.com/ianmiell/gitdags)

Branching model proposal (draft)

During the last TSC meeting we discussed about reviewing the branching model used for our projects.

Here we'll be describing how the model we (Marco and I) mentioned works and its peculiarities.

Note: to simplify our lives we will use the commands pre Git v2.23.0 (git switch and git restore aren't that used yet).

Description

In this model we operate with the main development line (master) and release branches (e.g. 1.0.x, 1.1.x, 1.2.x). This provides a lot of flexibility whilst keeping a single workflow.

Working on new features

This depends on the needs of the project.

For the simple ones, we branch-off master and merge things back to master:

feature-simple

Other projects might need multiple development lines. An example is Doctrine ORM that has 2.8.x as the development line for simple features and deprecation notices and master for the next major release (3.x-dev).

As you can imagine this is more complex since the features are implemented targeting the specific development lines (and syncronised to master):

feature-complex

Working on bug fixes

Some projects only offer active maintainance for the latest supported version, which simplifies things quite a lot. In this scenario we'd only need to apply fixes for bugs for the latest release branch (then syncronised it with master):

bug-simple

If we do need to have maintaince of older versions, the fixes should be applied on the version which introduced the issue (then syncronised all way to master):

bug-complex

Releasing

TBD

Synchronising branches

To keep branches synchronised we use merge-ups.

That consists in getting the changes of a specific released branch merged all the way up to master. This ensures that all release branches and the master branch are up-to-date and will never present a bug which has already been fixed.

Example

Let's say we've released the versions 1.0.0 and 1.1.0. New features are being developed on master (1.2.x-dev). After a couple weeks, a bug was found on version 1.0.0.

The fix for that bug should be done based on the branch 1.0.x and, once merged, the branches should be updated in this way:

  1. Create a branch from the fixed 1.0.x (git checkout 1.0.x && git checkout -b merge-up/1.0.x-into-1.1.x)
  2. Create a PR using 1.1.x as destination
  3. Create a branch from the fixed 1.1.x (git checkout 1.1.x && git checkout -b merge-up/1.1.x-into-master)
  4. Create a PR using master as destination

⚠️ when the merge-up can't be merged due to conflicts, we'd need to sync it with the destination branch. That's done by merging the destination into the merge-up branch and resolving the conflicts locally:

  1. Checkout to merge-up branch (git checkout -b merge-up/1.1.x-into-master)
  2. Sync merge-up branch (git merge --no-ff origin/master)
  3. Solve conflicts (using git mergetool or through an IDE)
  4. Resume merge (git merge --continue)
  5. Push (git push)
\documentclass[preview]{standalone}
\usepackage{subcaption}
\usepackage{gitdags}
\begin{document}
\begin{figure}
\begin{subfigure}[b]{\textwidth}
\centering
\begin{tikzpicture}
% Commit DAG
\gitDAG[grow right sep = 2em]{
A -- B -- {
C -- D -- {
J -- K,
I -- K,
},
E -- {
G -- H -- I,
F -- H
}
}
};
% Branch
\gitbranch
[1p0px]
{1.0.x} % node name and text
{below=of H} % node placement
{H} % target
\gittag
[v1p0p0] % node name
{1.0.0} % node text
{below=of B} % node placement
{B} % target
\gittag
[v1p0p1] % node name
{1.0.1} % node text
{below=of 1p0px} % node placement
{1p0px} % target
\gitbranch
{fix-bug} % node name and text
{below=of F} % node placement
{F} % target
\gitbranch
[1p1px]
{1.1.x} % node name and text
{right=of I} % node placement
{I} % target
\gittag
[v1p1p0] % node name
{1.1.0} % node text
{above=of D} % node placement
{D} % target
\gittag
[v1p1p1] % node name
{1.1.1} % node text
{right=of 1p1px} % node placement
{1p1px} % target
\gitbranch
{master} % node name and text
{above=of K} % node placement
{K} % target
% HEAD reference
\gitHEAD
{above=of master} % node placement
{master} % target
\end{tikzpicture}
\end{subfigure}
\end{figure}
\end{document}
\documentclass[preview]{standalone}
\usepackage{subcaption}
\usepackage{gitdags}
\begin{document}
\begin{figure}
\begin{subfigure}[b]{\textwidth}
\centering
\begin{tikzpicture}
% Commit DAG
\gitDAG[grow right sep = 2em]{
A -- B -- C -- {
H -- I -- J -- K,
D -- {
E -- G -- K,
F -- G,
}
}
};
% Branch
\gitbranch
[1p0px]
{1.0.x} % node name and text
{below=of B} % node placement
{B} % target
\gittag
[v1p0p0] % node name
{1.0.0} % node text
{below=of 1p0px} % node placement
{1p0px} % target
\gitbranch
{fix-bug} % node name and text
{below=of F} % node placement
{F} % target
\gitbranch
[1p1px]
{1.1.x} % node name and text
{below=of G} % node placement
{G} % target
\gittag
[v1p1p0] % node name
{1.1.0} % node text
{above=of C} % node placement
{C} % target
\gittag
[v1p1p1] % node name
{1.1.1} % node text
{below=of 1p1px} % node placement
{1p1px} % target
\gitbranch
{master} % node name and text
{above=of K} % node placement
{K} % target
% HEAD reference
\gitHEAD
{above=of master} % node placement
{master} % target
\end{tikzpicture}
\end{subfigure}
\end{figure}
\end{document}
\documentclass[preview]{standalone}
\usepackage{subcaption}
\usepackage{gitdags}
\begin{document}
\begin{figure}
\begin{subfigure}[b]{\textwidth}
\centering
\begin{tikzpicture}
% Commit DAG
\gitDAG[grow right sep = 2em]{
A -- B -- {
C -- {
E -- F -- M -- N,
D -- F
},
G -- {
H -- I -- J -- N,
K -- L -- J
}
}
};
% Branch
\gitbranch
[1p0px]
{1.0.x} % node name and text
{above=of B} % node placement
{B} % target
\gittag
[v1p0p0] % node name
{1.0.0} % node text
{above=of 1p0px} % node placement
{1p0px} % target
\gitbranch
[1p1px]
{1.1.x} % node name and text
{below=of J} % node placement
{J} % target
\gitbranch
{feature-a} % node name and text
{right=of D} % node placement
{D} % target
\gitbranch
{feature-b} % node name and text
{below=of L} % node placement
{L} % target
\gitbranch
{master} % node name and text
{above=of N} % node placement
{N} % target
% HEAD reference
\gitHEAD
{above=of master} % node placement
{master} % target
\end{tikzpicture}
\end{subfigure}
\end{figure}
\end{document}
\documentclass[preview]{standalone}
\usepackage{subcaption}
\usepackage{gitdags}
\begin{document}
\begin{figure}
\begin{subfigure}[b]{\textwidth}
\centering
\begin{tikzpicture}
% Commit DAG
\gitDAG[grow right sep = 2em]{
A -- B -- C -- {
D -- E -- F -- J,
G -- H -- I -- J,
}
};
% Branch
\gitbranch
{implement-new-feature} % node name and text
{below=of I} % node placement
{I} % target
\gitbranch
{master} % node name and text
{above=of J} % node placement
{J} % target
% HEAD reference
\gitHEAD
{above=of master} % node placement
{master} % target
\end{tikzpicture}
\end{subfigure}
\end{figure}
\end{document}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment