DEV Community

Cover image for Git tips for trunk-based development

Git tips for trunk-based development

Alessandro Diaferia on December 06, 2019

Trunk-based development is a source code branching model aimed at mitigating code integration and delivery risk. If implemented successfully, it he...
 
tonivdv profile image
Toni Van de Voorde

We could but we have some pre-requisites before doing that:

1) reviews through PR => ensures knowledge transfer and code quality
2) ci => ensures tests are passing, code quality/styling, and many other stuff
3) pushing to remote branch while not finish, prevents potentially losing code in case of theft of portable during home<->work trip, portable breaks, etc ..

And imagine 10 developers pushing without any checks on master ... yes it's called "trunk based development", but you should not take that literally ;)

Also, our master is protected to any modification involving history re-write. Going through a branch allows more flexibility ...

To give you an idea, our branches live approximatively 1 to 3 days tops ... In the past when we did not have feature flags in place and had to wait a feature was releasable that branch could stay for weeks and in some cases months ... And that's the big difference.

Collapse
 
tonivdv profile image
Toni Van de Voorde

Feature branching is when you finish a full feature and then only you merge it back to trunk/master. When doing this on a very big feature, this will lead to long-living branching, which is a real pain ... especially when working with multiple developers on a project.

However, when you e.g. doing agile and split a feature/epic into multiple (dev) stories/tasks , the idea is that every time a story is finished it is merged in trunk/master. Obviously if this merged story cannot be seen by the end user, you'll have to come up with solutions like e.g. the use of feature flags/toggles.

So yes, those tips of Alessandro are very valid. I use all of them on my project where we are doing trunk based development with 10 developers ;)

Collapse
 
tsalikispk profile image
Kostas Tsalikis

Great post, thank you! There is also a way to configure pull commands to rebase and auto-stash by default:

git config --global pull.rebase true
git config --global rebase.autoStash true

(credits to cscheng.info)

Collapse
 
sivaraam profile image
Kaartic Sivaraam

Just wanted to post a little note about the following point:

Both commands accept a stash reference (in the form of stash@{}) which you can use to unstash specific changes.

You don't have to explicitly specify git stash apply stash@{1} (or) git stash pop stash@{0}. Just passing the number would work fine too i.e., you can use them as follows:

# Pops (apply and drop) the last stashed change
git stash pop 0

# Applies the last stashed change
git stash apply 0
Collapse
 
alediaferia profile image
Alessandro Diaferia

Love it, thank you!

Collapse
 
fly profile image
joon

Never really tried to study git in-depth because sourcetree did everything I needed pretty much all the time. Might need to reconsider after reading this. Thank you for the post, a very informational read! :)

Collapse
 
dricomdragon profile image
Jovian Hersemeule

Thanks for this article ! A comment about your PRO tip for interactive git rebase. Instead of counting the number of commits since you diverged from master (like git rebase -i HEAD~7), you can directly give the branch ref :

git rebase -i master

Then it works the same. No need to use git log master.. 😉

Collapse
 
alediaferia profile image
Alessandro Diaferia

That's a great tip, thank you!

Collapse
 
itayronen profile image
Itay Ronen

I agree the article is not really about Trunk-based development, but it does not negate it.
You can work on a feature branch and merge to the "Trunk" (master).
trunkbaseddevelopment.com/short-li...

Collapse
 
alexisfinn profile image
AlexisFinn • Edited

I kindof use this at work:

  • branch
  • commit + push
  • commit --amend + push --force (to try and keep one commit)
  • rebase --interactive HEAD~x|sha1 to squash commits into one (this shouldn't happen because of the commit --amend, but well it does)
  • rebase master

---> go on to Merge Request.

The main problem with this approach is that while it does keep everything pretty clean, it messes up the history, crippling commands such as:

  • git blame: author can't be trusted because of squashing commits
  • git bisect: still works but since commits tend to become huge, it doesn't help much
  • git revert: same problem, commits tend to become huge so reverting a whole commit is usually out of the question

It's also pretty dangerous because when doing a push --force, if you don't pay attention at some point... well you're pretty much F'd (actually you can go explore the reflog, but that shouldn't happen)

So whereas it does make things more streamlined and easier to manage cherry-picking features into a production branch, it seriously diminishes the capabilities and reliability of the versioning system.

So i'm not saying its a bad process, I actually kind of like it, but boy does it get stressfull when the new junior dev/intern starts working because there's the potential to mess things up real bad real quick.

Collapse
 
tonivdv profile image
Toni Van de Voorde

If you are using a cloud solution like github/bitbucket you can protect your branches to avoid messing it up.

About the history being messed up, well this usually happens when working on long living branches. Here the idea is that you don't have that, so there shouldn't be different authors working on a branch. And even if that is the case, it's not mandatory to squash to merge back to master once it is done. You can even keep the full history if that is what you prefer.

We tend to not squash doing PR reviews ... we only squash when putting everything back in master. And that is only in the case of small short lived branches. In very rare cases we didn't squash.

Collapse
 
alexisfinn profile image
AlexisFinn

I get that the method I'm currently using (abiding by?) is not exactly the same thing, and I actually really like rebasing and commit --amending or squashing. I think it makes for a clean, easier to manage repository.

That being said I just thought I'd point out some of the potential drawbacks to going this route which has a lot to do with User error.

I've met a lot of devs who had a hard time visualizing what was happening with Git, either because they're used to SVN or just because it's not an easy tool to apprehend.

I've also met a good number of project managers / client demands that really don't lend very well to small iterative branches and commits, I have often ended up working several weeks on a single feature.

So whereas I truly like this approach, it should be carefully thought over if your team is not very proficient with git or your manager prefers long all-encompasing features and branches over small ones.

But of course you're right that there are many ways in which you can safegard against dramatic problems or event circumvent them entirely through a well thought out branching tree, and that is one of the beauties of Git: It can pretty much do it all.

Collapse
 
itayronen profile image
Itay Ronen

The author did not recommend to squash all your commits into one.
I recommend you to do use commits to split your work and make PR easier and history cleaner.
Use rebase to edit your commit history and apply it on top of master.
Then when you go to PR, the reviewer will see your (edited) commits, on top of master.

Collapse
 
dlcardozo profile image
Diego Cardozo

Have you tried to use feature toggles and only have one branch all the time?

In my daily basis I work with artists, devs and more roles in the same branch without merges and each commit is production ready, we just toggle what is not ready for the real world, but the trick is that we always work in pairs when we are in our domain (DDD) that allow us to remove the need of PRs.

But lets be honest, to have a pure TBD like what I said before you need three things, One branch, Feature Toggles and fast approval of each commit (for this we use pair programming)

Trunk Based Development can be simpler and should be, thanks for these tips!

Collapse
 
alediaferia profile image
Alessandro Diaferia • Edited

Trunk-based development doesn't negate the use of branches. As long as they are short-lived they ease reviews and help keep master (trunk) in a deplorable state all the times: trunkbaseddevelopment.com/short-li...

Collapse
 
hasii2011 profile image
Humberto A Sanchez II

Nice article

Collapse
 
geewiz profile image
Jochen Lillich

Very good overview of a clean merging workflow! I’ll recommend it to our team.

Greetings from Bray!

 
alediaferia profile image
Alessandro Diaferia

I agree, pure trunk-based development would work off a single trunk, always. But you still will need to rebase before pushing to master :)

Thread Thread
 
alediaferia profile image
Alessandro Diaferia

I would love to hear about your workflow. How many developers do you work with managing to keep a pure trunk-based development? How long does your full testing pipeline take to execute? Do you allow multiple people to push to master even before a full pipeline has finished executing? How do you ensure all your modifications are feature-flagged or how do you coordinate the release of new functionality? Do you have a testing pyramid or how are your testing efforts balanced? Is it a B2B or B2C software? Do you have automated roll-backs if a change introduces an outage? Do you halt pushing to master if the changes introduced a high severity issue that has not been caught by your automated tests?

Thread Thread
 
shirishp profile image
Shirish Padalkar

We have a team of 15+ developers and all of our development is always on trunk / master.
Our testing pipeline takes less than 10 minutes to execute end to end.
We do not restrict any pushes to master, so multiple people can push to master even before the build is completed.
We trust people to make sure their code is always ready to release to production, or when it's not, put it behind a feature toggle. If something still goes wrong, we feel our test suite is good enough to catch such problems.

I think to make this happen, you do need a higher level of trust on people to do the right thing. And for context sharing, we do pair programming, which helps a lot.

Thread Thread
 
alediaferia profile image
Alessandro Diaferia

That is just awesome. Is it a user-facing product? What's your testing allocation like between unit, integration, e2e? Is it a single repo between front end and back end code?

Thread Thread
 
shirishp profile image
Shirish Padalkar

Thanks. Yes, it is a user facing product. We have React based frontend, which is unit tested and 7-8 microservices which are also unit tested. We do have API level integration tests to cover interactions between services. And finally, we are in process of writing UI based functional tests to cover user flows.

So far, it's been working out pretty great. But I do want to call out that the team is extremely disciplined about the workflow and hence we haven't seen any problems. I do understand this might not be the case with all teams and each team might need a different variation of version control branching model.

Collapse
 
alexandrusimandi profile image
Alexandru Simandi

In trunk based development you control code with feature toggles and branch by abstraction. So technically there is source code branching, just not at VCS level

Collapse
 
lukaszsarzynski profile image
Łukasz Sarzyński

Great article, congratulate!

Collapse
 
rbukovansky profile image
Richard Bukovansky

So in basic you are bringing CVS/SVN development style Git is trying to avoid... 🤔

Collapse
 
alexandrusimandi profile image
Alexandru Simandi • Edited

This is a common misunderstanding about trunk based development. I use it at work daily, our pipeline is pushing the same code on both dev/staging and production. The only difference is in feature toggles. This forces you to think about the code in a different way. If the client complains about a certain build having an issue, you can just toggle back the old version of that feature, hell even the client can do that if it's an emergency using something like rollout.io/