Fun with Learning Technology
LearnCoursesQuestionsTracksToolsNewsExplorePractice
Fun with Learning Technology

A new problem, explained clearly, every day.

Subscribe
Learn
  • Lessons
  • Topics
  • News
  • Tools
  • Courses
  • Career tracks
  • Everything
Site
  • About
  • Contact
  • Support
  • Privacy
  • Terms
Get the daily one

One email per new problem. No spam.

Request a tutorial

Requests shape what gets made next.

© 2026 Fun with Learning TechnologyRSS
Home›Courses›Git & GitHub›Trunk-Based Development

Workflows

Trunk-Based Development

Trunk-Based Development is a version control strategy where all developers merge small, frequent updates to a single shared branch, known as the 'trunk'. It eliminates the complexity of long-lived feature branches, enabling continuous integration and faster feedback loops. This approach is essential for high-velocity teams aiming to reduce merge conflicts and deploy software continuously with high confidence.

The Philosophy of the Single Source of Truth

In Trunk-Based Development, the primary branch (often named 'main') represents the current state of the application at all times. By mandating that all developers integrate their work directly into this branch, the team avoids the 'integration hell' often caused by long-lived side branches. When you pull from the trunk frequently, you are forced to reconcile your changes against the most recent state of the codebase. This constant synchronization forces developers to break down large tasks into smaller, incremental pieces. Because no feature is isolated for more than a day or two, the gap between what you have written and what exists in production stays narrow. This reduces cognitive load during merges, as the differences are always minimal. It transforms integration from a high-risk event into a routine, low-risk habit that happens throughout the day.

# Fetch the latest state of the project from the remote server
git fetch origin

# Synchronize the local main branch with the central repository
git checkout main
git pull origin main

Incremental Commits and Small Batches

The effectiveness of this workflow relies on the granularity of your commits. Instead of working on a massive feature for weeks and performing a single giant merge, you should submit small, functional changes daily. Each commit should ideally represent a single logical step forward—perhaps a single function addition or a small logic tweak. This methodology allows for easier troubleshooting; if a breaking change reaches the trunk, you can identify exactly which commit introduced the regression without sifting through thousands of lines of code. Small batches also make code reviews more manageable. Reviewers are far more likely to provide high-quality feedback when reviewing fifty lines of code than five hundred. This iterative cycle keeps the entire development team aligned and ensures the project moves forward in a steady, predictable rhythm.

# Check the status of your current work to prepare for a small, logical commit
git status

# Add specific files related to this tiny improvement
git add src/auth_service.py

# Commit with a descriptive message explaining the specific change
git commit -m "Refactor authentication logic for improved validation"

Managing Incomplete Features with Feature Flags

When you are forced to merge into the trunk daily, you might worry that unfinished code will break the application for everyone else. This is where feature flags become indispensable. Instead of hiding your work in a separate Git branch until it is perfect, you merge the code directly into the trunk but wrap the new functionality in a conditional check. In production, this flag remains set to 'off', keeping the new path unreachable for users. Once the feature is fully tested and ready, you simply toggle the flag to 'on'. This separates the concept of 'code deployment' from 'feature release'. By using this pattern, you ensure that the main branch remains stable and deployable at all times, even while you are actively building and testing significant new capabilities in the background.

# Create a temporary branch only to work on a specific feature with a flag
git checkout -b feature-user-dashboard

# Logic implementation wrapped in a configuration flag
# if config['enable_dashboard']:
#    run_dashboard_logic()

# Merge to main immediately, even if feature is incomplete
git checkout main
git merge feature-user-dashboard

Handling Merge Conflicts Early

Merge conflicts are inevitable in a collaborative environment, but they are significantly less painful when they occur frequently. In a branching-heavy workflow, conflicts often accrue for days or weeks, leading to massive, confusing resolution sessions. In Trunk-Based Development, because you are pulling from the main branch multiple times a day, you will likely only encounter conflicts on a small set of files that were changed just moments ago. This proximity to the actual changes makes resolution straightforward because the context of the code is still fresh in your mind and your teammate's mind. Addressing these tiny collisions immediately prevents them from snowballing into systemic failures. By treating integration as a constant background process rather than a final event, you maintain the health of the shared codebase without interrupting team velocity.

# Attempt to pull the latest changes into your local branch
git pull origin main

# If a conflict arises, git will pause; resolve the file markers manually
# Edit the conflicting files, then mark them as resolved
git add <conflicted_file>
git commit -m "Resolve integration conflict after pull"

Keeping the Trunk Deployable

The ultimate goal of this workflow is to ensure the trunk is always in a releasable state. If the build breaks, it must be treated as the highest priority issue and fixed immediately by the team. This implies that testing must be automated and fast. Every time code is pushed, automated tests should run to verify that existing functionality remains intact. If a change fails, the author is responsible for reverting or patching it immediately. This culture of accountability prevents the 'broken window' syndrome where developers stop caring about the state of the branch because it is permanently unstable. When the trunk is protected by a solid test suite and a disciplined team, you gain the agility to deploy to production at any moment, which is the hallmark of a high-performing engineering team.

# Verify the current state of the main branch before submitting
git checkout main

# Always run local tests to ensure no regressions were introduced
# test_suite --run-all

# Push the confirmed, working code to the remote repository
git push origin main

Key points

  • Trunk-Based Development centers on frequent integration into a single shared branch.
  • Small commits are essential to minimize the difficulty of managing merge conflicts.
  • Feature flags allow developers to merge incomplete code without breaking the application for users.
  • Continuous synchronization with the remote trunk prevents long-lived branches from diverging.
  • The trunk must always remain in a stable, deployable state for the entire team.
  • Frequent integration forces developers to resolve technical debt and logic conflicts immediately.
  • Code reviews are more effective when they happen on small, atomic changesets.
  • Automated testing is a necessary requirement to maintain confidence in the trunk's stability.

Common mistakes

  • Mistake: Keeping local branches open for weeks. Why it's wrong: It leads to massive merge conflicts and 'integration hell.' Fix: Merge to main and delete the branch daily.
  • Mistake: Committing broken or untested code to main. Why it's wrong: It breaks the build for everyone on the team. Fix: Use pre-commit hooks and local CI tests before pushing.
  • Mistake: Creating massive, all-encompassing pull requests. Why it's wrong: It makes peer review impossible and increases the risk of regressions. Fix: Keep changes small and scoped to a single feature or fix.
  • Mistake: Skipping the pull/rebase step before pushing to main. Why it's wrong: It causes diverging histories and rejected pushes. Fix: Always rebase your work on the latest main before integration.
  • Mistake: Using 'git merge' with squash for every tiny commit. Why it's wrong: It destroys the historical context of the development process. Fix: Use atomic commits and merge only when the feature is complete and verified.

Interview questions

What is the core philosophy behind Trunk-Based Development in a Git environment?

The core philosophy of Trunk-Based Development is to keep the main branch—often called 'main' or 'master'—in a deployable state at all times by having all developers merge small, frequent updates directly into it. Instead of working on long-lived feature branches, developers commit code daily. This minimizes 'merge hell,' encourages continuous integration, and ensures that the codebase remains stable, allowing for a much faster feedback loop when using Git for version control.

How does Trunk-Based Development change the way a developer uses Git branches?

In Trunk-Based Development, you move away from creating long-lived branches that last for weeks. Instead, you create very short-lived branches that exist for only a few hours or, at most, a couple of days. Once the work is complete, you use a Pull Request to merge these small changes back into the main branch immediately. This forces developers to break down large tasks into smaller, manageable chunks that are easier to review and test within Git.

Why is it important to use 'feature flags' when practicing Trunk-Based Development?

Feature flags are essential because they allow you to merge incomplete code into the main branch without actually exposing that feature to end users. By wrapping new code in a conditional check, you can safely push to production while the code is hidden behind a configuration toggle. This allows you to maintain the 'main' branch in a deployable state while still continuously integrating your work into the repository, effectively decoupling deployment from release.

How do you handle merge conflicts in a Trunk-Based workflow compared to Gitflow?

In Trunk-Based Development, you handle conflicts by pulling updates from the main branch frequently—often multiple times a day—and resolving discrepancies immediately. Because your branch is short-lived, the delta between your code and the main branch is small, making conflicts trivial to solve. In contrast, Gitflow often involves long-lived feature branches, which lead to massive, complex merge conflicts when eventually merging back into the main trunk after weeks of diverging, creating significant technical debt and integration headaches.

Can you compare Trunk-Based Development with the Gitflow branching strategy?

Gitflow relies on multiple permanent branches like 'develop' and 'release', with strict workflows for feature and hotfix branches. It is highly structured but slow, often causing bottlenecks. Trunk-Based Development, however, encourages merging directly into 'main' via small, frequent commits. While Gitflow is safer for rigid, infrequent release cycles, Trunk-Based Development is superior for modern CI/CD pipelines because it eliminates the overhead of managing complex branch hierarchies, fosters higher team velocity, and reduces the integration risks associated with long-lived feature branches.

If you are working in a team using Trunk-Based Development, how should you structure your commits and pull requests to ensure success?

To succeed, you must adopt an 'atomic commit' strategy where each Git commit contains exactly one logical change. Your pull requests should be kept intentionally small, ideally touching only a few files, to make them easy for teammates to review in minutes rather than hours. For example: `git commit -m 'Add user validation logic'` instead of bundling three features together. This transparency ensures that if a break occurs, `git bisect` can quickly isolate the specific commit that introduced the regression, keeping the main branch healthy.

All Git & GitHub interview questions →

Check yourself

1. What is the primary goal of Trunk-Based Development in a Git workflow?

  • A.To enforce a strict hierarchy of repository administrators
  • B.To minimize the duration of branch divergence from the main line
  • C.To prevent developers from using the command line
  • D.To ensure every single commit is deployed to production instantly
Show answer

B. To minimize the duration of branch divergence from the main line
Trunk-based development focuses on merging small, frequent updates into the main branch to avoid long-lived branches. Other options describe bureaucratic controls, platform limitations, or CI/CD deployment strategies rather than the core Git branching philosophy.

2. When a developer is working on a feature in a short-lived branch, what should they do before merging into main?

  • A.Delete the remote repository and recreate it
  • B.Rebase their branch against the current main branch to incorporate upstream changes
  • C.Create a new branch for every file they modified
  • D.Force push their local branch to main to ensure it overwrites history
Show answer

B. Rebase their branch against the current main branch to incorporate upstream changes
Rebasing ensures the local branch is up-to-date with the main line, avoiding conflicts during the merge. Forcing pushes or recreating repositories breaks history and collaboration, while multiple branches for one feature defeat the purpose of trunk-based flow.

3. How does Trunk-Based Development change the role of the Pull Request (PR) compared to long-lived branching strategies?

  • A.PRs are eliminated and replaced by physical mail
  • B.PRs are used only for final release candidates
  • C.PRs become smaller and shorter-lived to facilitate rapid code review
  • D.PRs are restricted to senior developers only
Show answer

C. PRs become smaller and shorter-lived to facilitate rapid code review
In trunk-based development, the goal is to keep PRs small so they can be reviewed and merged quickly. Eliminating them or limiting them by seniority/release phase contradicts the goal of continuous integration.

4. Why are 'long-lived' feature branches considered detrimental in a team environment?

  • A.They are incompatible with the Git graphical interface
  • B.They make it difficult to identify integration errors until late in the development cycle
  • C.They use too much local disk space on the developer's machine
  • D.They force the use of submodules
Show answer

B. They make it difficult to identify integration errors until late in the development cycle
The longer a branch exists, the more it drifts from the main code base, leading to 'integration hell.' The other options are misconceptions about Git's technical constraints or features.

5. What is the recommended approach for handling unfinished features in a trunk-based environment?

  • A.Commit only to a hidden local file not tracked by Git
  • B.Merge the unfinished code and hope it compiles
  • C.Use feature flags to merge code into main while keeping the functionality disabled
  • D.Keep the branch open for months until the feature is perfect
Show answer

C. Use feature flags to merge code into main while keeping the functionality disabled
Feature flags allow teams to integrate code into main continuously without exposing unfinished features to users. Merging broken code is bad practice, and keeping branches open defeats the trunk-based philosophy.

Take the full Git & GitHub quiz →

← PreviousGitflow WorkflowNext →Conventional Commits

Git & GitHub

20 lessons, free to read.

All lessons →

Track your progress

Sign in to mark lessons done, score quizzes and keep notes.

Open in the app