softwareengineering

this is a robotics team with some questions.

Here’s our current setup, using GitLab:
Currently, we have a main branch as well as a separate branch for each of our programmers. When they want to start working, they pull main and merge local main into their local personal branch (personal meaning the branch that has their name on it). From there they make the changes they want to, push that up, and initiate an MR. The lead programmer approves the MR and merges it in to main.

Here’s a what if scenario that causes issues for us (fake names):
Fred starts working, updating his personal to be up-to-date with main. So, he starts from commit A. He’s made changes as commits 1 and 2 on his personal branch (A-1-2), when Bob makes an important, time-sensitive fix and it gets merged into main right away, as commit B (A-B). How does Fred update his personal branch to include B in a way that doesn’t cause issues down the line when his branch gets merged into main?

Currently, the idea is rebase main onto personal, which if I understand correctly would make A-B-1-2. However, in our experience this causes issues with pushing to the remote personal itself.

My big question is:
Should our branches be set up differently? For example, branches get created for individual features and then deleted, instead of keeping personal branches around and constantly updating them. Would this solve our problems, or at least some of them? Should we not have remote personals, and should we then be using git rebase?

Firstly, gitlab have their own opinion on how users should work called Gitlab flow. I’ve not read all of that in detail but it seems to be a feature branch based workflow.

He’s made changes as commits 1 and 2 on his personal branch (A-1-2), when Bob makes an important, time-sensitive fix and it gets merged into main right away, as commit B (A-B). How does Fred update his personal branch to include B in a way that doesn’t cause issues down the line when his branch gets merged into main?

Fred should pull from main. This will trigger a merge, at which point he should resolve any conflicts. He can then continue adding commits and eventually merge back into main.

rebase main onto personal, which if I understand correctly would make A-B-1-2. However, in our experience this causes issues with pushing to the remote personal itself.

I think you mean “rebase personal on to main”? Yes, basically once you have done a rebase you can’t do a normal push and have to force push. This is messy and I would advise against having a “remote personal” in the first place. Indeed, why do you have a personal branch at all? To what extent do you benefit from each having different independent versions of the software?

If you want to keep personal branches, rebased or not, AND use feature branches, that is also possible:

  • create feature branch from main
  • merge personal on to feature
  • push feature
  • create MR from feature to main
  • further work on personal
  • either merge personal to feature again, or cherry-pick individual commits to include in MR
  • keep personal updated by doing pull remote main->local main; merge-pull local main->personal. (Recall that “git pull” is “git fetch” + “git merge” or “git rebase” depending on config setting “pull.rebase”).

In git, a lot of things are possible. This can cause problems because not everything that is possible is a good idea.

4

Should our branches be set up differently? For example, branches get created for individual features and then deleted

Yes, that is definitely a standard approach
which works well in production for many teams.

Someone, perhaps your lead programmer, is managing
a backlog of desired features.
Execute weekly Sprints, or perhaps two-week long sprints.
During sprint planning, bring forward any accidental “left over”
features, then plan to produce certain high-priority features,
creating a ticket for each one.

When developer Fred becomes ready to tackle a feature
they create new branch from main which has the Issue ticket number
in it. All edits should relate just to that feature.
In particular, we won’t see the unrelated B commit in this branch.

At some point the feature is implemented, tested, and considered “done”,
ready for review.
Either the edits will merge cleanly or there are conflicts to resolve.
Usually at this point Fred would merge in B from main,
tidy things up so tests are once again Green,
and request review of new MR.
Occasionally B might be “tricky”,
enough that we temporarily ignore B and someone like team lead
will take responsibility for tidying things up.
In which case we await review approval,
and turn it over to that person for final merge.

Fred will typically implement one or more features
in the course of a sprint, each in their own short-lived branch.
(Occasionally it’s useful to create branch Y
from related feature branch X if X is still stuck in review
and we want to get coding.)
I have worked with teams of diverse abilities
and have seen this “short-lived branch” approach
work smoothly for many sprints without rebasing
and without merge troubles.
Your team should be productive when adhering to it.
A more sophisticated team might opt for something
more elaborate; that’s something that can always
be decided later after a bunch of sprints go smoothly for you.


You might prefer “merge squashing” after review approval.
That way the several commits from feature development
show up in git blame with just a single timestamp.
It tends to make “blame” output more readable,
especially when multiple developers add features
to a single source file.

3

LEAVE A COMMENT