Tower Blog https://www.git-tower.com/blog Wed, 18 Feb 2026 00:00:00 +0000 Tower Blog - About Web and Software Development, Marketing and Design Exploring the .git Directory – How Git Stores Your Code https://www.git-tower.com/blog/exploring-the-git-directory https://www.git-tower.com/blog/exploring-the-git-directory Wed, 18 Feb 2026 00:00:00 +0000 We all use Git every day, but how many of us truly understand what's happening behind the scenes? Today, we're going to bravely venture inside the .git directory, unpack its most important contents, and demystify how Git actually works.

There's a mysterious .git folder at the root of every repository. You probably know that this folder serves as the brain, heart, and engine room of your project's version control system, even though it is often ignored and sometimes feared.

If you've ever wondered what types of files and folders exist inside this magical folder, then this tour is for you.

Ready for some enlightenment? Let's dive in!

1. What is the .git directory for?

At its core, Git is a content-addressable filesystem, and the .git directory is where all that content (and the pointers to it) lives. It's the repository itself, containing everything Git needs to know about your project's history, branches, configuration, and more. Your working directory (where your actual files are) is just one projection of what's inside .git.

Let's start by listing its contents. Navigate to the root of any Git repository in your terminal and type ls -F .git/. You'll see something like this:

branches/        HEAD        hooks/        logs/        objects/        refs/        config        description        index        info/

The exact contents might vary slightly depending on your Git version and repository state. Please note that the branches/ directory is a legacy remnant from older versions of Git and is no longer used in modern repositories.

You may also notice a COMMIT_EDITMSG file in the listing, which stores the message from your most recent commit that Git uses when you run git commit --amend.

Each of these files and directories plays a crucial role. Let's break them down.

2. The HEAD File (Your Current Position)

One of the most fundamental files in .git is HEAD. It's usually a simple text file that contains a reference to your current branch.

# Example content of .git/HEAD when on the 'main' branch
cat .git/HEAD
# Output: ref: refs/heads/main

This tells Git that your current HEAD (your "current commit") is the latest commit on the main branch.

What about a "Detached HEAD"?

When you git checkout <commit-hash>, the HEAD file changes to point directly to a commit hash, rather than a branch.

# Example content of .git/HEAD in a detached HEAD state
cat .git/HEAD
# Output: 8b0e7a2b... (40-character SHA-1 hash)

This is a "detached HEAD" state. It means you're directly on a commit, not on a branch. This simple file's content is the key to understanding a concept that often confuses new users!

Not a Tower user yet?

Download our 30-day free trial and experience a better way to work with Git!

Tower app icon

3. The config File (Your Project's Local Settings)

You've likely used git config from the command line. This is Git's configuration system, which is immensely customizable.

The config file is where your local, repository-specific configurations are stored.

# Example content of .git/config
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = https://github.com/your-org/your-repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

This file contains settings like remote URLs, branch tracking information, and any specific overrides for this particular repository. It's neatly organized into [sections].

4. The index File (Staging Area)

The index file is a crucial binary file that represents your "staging area" or "cache". It is a dynamic snapshot of your project's state that is waiting to be committed.

When you run git add <file>, Git takes the current version of that file from your working directory, computes its hash, stores it in the objects directory, and updates the index file to record that this new version of the file is now staged for the next commit.

5. The objects Directory (The Heart of Git)

This is where the magic truly happens. The objects directory is Git's content-addressable database. Every piece of content — every file, every directory state, every commit message — is stored here as an "object", identified by its SHA-1 hash.

Inside objects/, you'll find subdirectories named after the first two characters of the SHA-1 hash. This helps distribute the objects more evenly across the filesystem. The remaining 38 characters form the filename itself, so a full object path looks like .git/objects/8b/0e7a2b9d1f3c5e7a9b2d4f6e8c0a1b3d5f7e9a.

There are three main types of objects:

  • Blob Objects: These store the actual content of your files. If two files have identical content, Git only stores one blob object and points to it twice.
  • Tree Objects: These represent the state of a directory at a given point in time. They contain a list of pointers to blob objects (for files) and other tree objects (for subdirectories). This is how Git stores directory structures efficiently.
  • Commit Objects: These are the commits you create. Each commit object stores:
    • A pointer to the top-level tree object for that commit (the root directory snapshot).
    • Pointers to its parent commit(s).
    • Author and committer information.
    • The commit message.

This elegant system means Git doesn't store "diffs" between file versions. Instead, it stores full snapshots, and computes the differences on the fly when you ask for them.

That said, you may also notice a pack/ subdirectory inside objects/. For efficiency, Git periodically compresses objects into binary pack files using delta compression — so while conceptually Git stores full snapshots, on disk it optimizes storage behind the scenes (you can trigger this manually with git gc).

6. The refs Directory (The Pointers)

The refs directory is where Git stores simple pointers to specific commit objects. This is where your branches and tags truly live.

  • refs/heads/: Contains one file for each local branch (e.g., refs/heads/main, refs/heads/feature/login). Each file contains the SHA-1 hash of the commit that branch currently points to.

    # Example content of .git/refs/heads/main
    cat .git/refs/heads/main
    # Output: 8b0e7a2b9d1f3c5e... (the latest commit on 'main')

    This means that a branch is nothing more than a movable pointer to a commit. Moving a branch (e.g., with git commit or git reset) simply means updating the SHA-1 hash in this file.

  • refs/tags/: Similar to heads, but for tags. Each file contains the SHA-1 hash of the commit (or tag object) that the tag points to. Tags are generally immutable pointers.

  • refs/remotes/: Tracks the state of branches on remote repositories (e.g., refs/remotes/origin/main).

7. hooks and logs (Automate and Observe)

Finally, two more important directories:

  • hooks/: This directory contains sample scripts (e.g., pre-commit.sample, post-merge.sample) that you can rename and activate. These are your Git Hooks, allowing you to run custom scripts before or after certain Git events. They're powerful for enforcing code quality, running tests, or deploying code. You can learn more about Git Hooks here.

  • logs/: This is where Git keeps its reflog (reference logs). The reflog is an incredibly useful safety net that records every time your HEAD (or a branch) has been updated. This means you can almost always recover "lost" commits or branches, as we discussed in our article on Force Push disaster recovery.

Final Words

If you've made it this far, congratulations! You're not just using Git anymore; you're truly understanding it!

By taking this guided tour of the .git directory, you now realize that Git is not a complex, magical black box, but an elegant and robust system built upon simple, interconnected objects and pointers. Now, if something goes wrong, you'll have a better intuition for troubleshooting.

For more in-depth guides, don't forget to sign up for our newsletter below and follow Tower on Twitter and LinkedIn!

]]>
Tower 11 for Windows — Commit Templates https://www.git-tower.com/blog/tower-windows-11 https://www.git-tower.com/blog/tower-windows-11 Mon, 02 Feb 2026 00:00:00 +0000 We are thrilled to announce the release of Tower 11 for Windows! This version introduces a feature that many of you have been waiting for: Commit Templates!

Get ready to craft better commits and bring more consistency to your project's history! 😎

Clear and descriptive commit messages are the backbone of a healthy Git repository. They make it easier to understand changes, review code, and track down bugs. But maintaining a high standard for commit messages across a whole team and over the long run is a tough challenge.

That's where Git's "Commit Templates" come to the rescue! And with Tower 11 for Windows, using them is now incredibly simple.

Let's dive in and see how you can start using this feature today.

Your Command Center for Commit Templates

You can manage all your commit templates in Tower's Preferences, under the new "Templates" tab. We've included a default template to get you started, but the real power comes from creating your own.

Tower 11 for Windows – Managing Commit Templates
Tower 11 for Windows – Managing Commit Templates


To create a new template, just click the "+" button and fill in the details. If you're not sure what to include in your commit template, this blog post can teach you all the fundamentals on how to write a compelling commit message.

Tower 11 for Windows – Creating a new Commit Template
Tower 11 for Windows – Creating a new Commit Template


You can set a global default template that will be used for all your repositories. Or, for more fine-grained control, you can define a specific template for a particular repository in its settings.

Tower 11 for Windows – Repository Settings
Tower 11 for Windows – Repository Settings

Inserting a Template When Committing

When you're ready to commit, you'll find a new "Commit template" button in the commit composer. Clicking it will reveal all your saved templates.

Tower 11 for Windows — Commit Template button
Tower 11 for Windows — Commit Template button


For the keyboard ninjas out there, we've got you covered too! Simply type "t:" or "/" in the commit subject field to bring up the template list and select the one you need without ever leaving the keyboard.

Tower 11 for Windows – Insert a Commit Template using the keyboard.
Tower 11 for Windows – Insert a Commit Template using the keyboard.

ARM-Native Version for Windows

We are also excited to announce that, starting with this release, Tower for Windows will be available as an ARM-native application!

Tower 11 for Windows — ARM-Native Version
Tower 11 for Windows — ARM-Native Version


If you are using a Windows device with an ARM processor, you can now enjoy a faster and more energy-efficient experience. This native ARM version ensures that Tower runs with the best possible performance on these devices.

The best part? If you're using a device with an ARM processor, you will automatically receive the ARM-native version when you update to version 11. There's no need to switch manually!

Other Improvements

As usual, we took some time to implement improvements across the board. Here's what's new:

  • Branch Naming: Spaces in branch names are now automatically replaced with dashes for improved consistency.
  • Bookmarks: The default path when adding a new repository is now synchronized with the default clone path defined in Preferences.
  • Licensing: Evaluation of license expiration dates has been improved.
  • GPG Configuration: Improved GPG configuration handling by providing system environment variables for the GPG config binary.
  • Portable Git: Updated to version 2.52.0 for improved compatibility and performance. Please note that git-flow was removed in version 2.51.2. To maintain compatibility, do not remove previous versions of Embedded Git and select version 2.51.0 in Preferences → Git Config → Git Binary.

We also fixed some bugs! Here is what we addressed:

  • Preferences: Fixed a crash that could occur when switching the SSH implementation to OpenSSH.
  • GPG: Fixed an issue with retrieving the GPG binary version.
  • Commit: Fixed string encoding issues when committing changes.
  • Working Tree: Addressed a potential crash when refreshing the working tree.
  • Rebase: Fixed an issue where running an interactive rebase could result in intermittent errors.
  • Remote Branches: Fixed parsing issues with remote branch names.

We can't wait for you to try Tower 11 for Windows! If you already have a Tower account, update to version 11 today!

Happy committing! 😊

Not a Tower user yet? Download our 30-day free trial and experience a better way to work with Git!




PS: Did you know? Tower Pro is now free for students as well as teachers and educational institutions!

]]>
The Ultimate Guide to Git Config: Fine-Tuning Your Git Experience https://www.git-tower.com/blog/the-ultimate-guide-to-git-config https://www.git-tower.com/blog/the-ultimate-guide-to-git-config Fri, 30 Jan 2026 00:00:00 +0000 You've probably used git config to set your name and email, but have you ever explored its other capabilities?

Git's configuration system is a treasure trove of settings that can dramatically improve your productivity and tailor Git to your exact needs. It’s like having a secret control panel for the world's most popular version control system!

But with dozens of options, where do you even start? Don't worry — we've got you covered.

In this comprehensive guide, we'll explore the ins and outs of git config, from the foundational settings to the "hidden gems" that will make you a Git power user.

Ready to customize your Git experience? Let's get started!

1. The What, Where, and How of Git Config

Before we dive into the cool stuff, let's get the basics right. Understanding how git config works is the foundation for everything else.

What is git config?

At its heart, git config is the command that lets you get and set configuration variables that control all aspects of Git's appearance and operation. These configurations can be as simple as setting your username or as complex as rewriting Git's core behaviors for diffing and merging.

The Three Levels of Configuration

Git provides three levels of configuration, each overriding the previous one:

  1. System (--system): These settings apply to every user on the entire machine. You'll rarely need to touch this. The file is typically located at /etc/gitconfig.
  2. Global (--global): This is where you'll set your personal preferences. These settings apply to all of your repositories. The file is located in your user's home directory (~/.gitconfig on Linux/macOS, C:\Users\<YourName>\.gitconfig on Windows). This is where the magic happens for most users!
  3. Local (--local): These settings are specific to the repository you are currently in. They are stored in the .git/config file inside your repository and are perfect for project-specific overrides.

This layered system gives you incredible flexibility. You can set a global preference and then override it for a specific project that has different needs.

Basic Commands

Interacting with these settings is straightforward. Here are the commands you'll use most often:

# View all settings (from all levels)
git config --list

# View a specific setting
git config user.name

# Set a global setting
git config --global user.name "Your Name"

# Set a local setting for the current repository
git config --local user.email "your-email@example.com"

# Remove a setting
git config --global --unset user.signingkey

Not a Tower user yet?

Download our 30-day free trial and experience a better way to work with Git!

Tower app icon

The Config File Syntax

While using git config --set is great, sometimes it's easier to open the .gitconfig file with your favorite text editor and edit it directly.

The syntax is simple and intuitive:

[section]
    key = value

# This is a comment
; This is also a comment

[alias]
    co = checkout
    st = status

[user]
    name = Bruno Brito
    email = bruno@git-tower.com

Sections are denoted by square brackets (e.g., [user]), followed by key-value pairs.

Modularizing Your Config with include

As your .gitconfig file grows, it can become a bit unwieldy. A fantastic feature for staying organized is include.path. It allows you to split your configuration into multiple files.

For example, you could keep all your Git aliases in a separate ~/.gitconfig-aliases file:

# In ~/.gitconfig
[include]
    path = ~/.gitconfig-aliases

Then, in ~/.gitconfig-aliases:

[alias]
    co = checkout
    st = status
    br = branch
    lg = log --oneline --graph --decorate

This keeps your main config file clean and makes your settings easier to manage or even share!

2. The Essentials: Your Identity and Core Settings

In this section, we will cover the essential settings that every developer should configure.

  • Setting Your Identity: This is the first thing you should do on a new machine. It ensures all your work is properly attributed to you.

    git config --global user.name "Your Name"
    git config --global user.email "your-email@example.com"
  • Choosing Your Default Branch Name: The default branch name in new repositories used to be master. The community has since shifted towards main. You can make main your default for all new projects:

    git config --global init.defaultBranch main
  • The Core Editor: When Git needs you to enter a message (like for a commit or a merge), it opens an editor. You should tell Git which one to use:

    # For VS Code
    git config --global core.editor "code --wait"
  • Handling Line Endings: To prevent issues when collaborating with people on different operating systems (Windows vs. Mac/Linux), it's a good practice to configure how Git handles line endings.

    # For macOS/Linux
    git config --global core.autocrlf input
    # For Windows
    git config --global core.autocrlf true
  • Ignoring File Permissions: Have you ever seen a file show up as "modified" when you only changed its executable permissions? This can be annoying. If you don't need to track file permissions, you can tell Git to ignore these changes:

    git config --global core.fileMode false

3. Productivity Boosters for Smoother Workflows

With the basics out of the way, let's look at some settings that will save you time and make Git more enjoyable to use.

Aliases: Your Personal Git Shortcuts

Aliases are one of the most powerful features in git config. They let you create your own shortcuts for longer commands.

[alias]
    # Simple shortcuts
    co = checkout
    st = status
    br = branch

    # A more complex log format
    lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

    # Run a shell command!
    purge = "!git branch --merged | egrep -v '(^\\*|main|develop)' | xargs git branch -d"

With the lg alias above, git lg gives you a beautifully formatted history. The purge alias lets you clean up all your merged local branches with a single command!

Controlling Your Git Output Color Palette

Since version 1.8.4, Git's output has become colorful, making it easier to read at a glance. However, if you prefer a more monochromatic appearance, you can adjust the settings by typing the following:

git config --global color.ui false

This single command disables color for Git's output (like diff, status, and branch) when you're using a terminal.

The Pager

Sometimes, a command's output is too long to fit on your screen (like git log). Git uses a "pager" (like less) to let you scroll through it but you can control this behavior.

For example, to disable the pager for git branch:

git config --global pager.branch false

With this setting, all branches will print directly to the terminal.

Rebase by Default

If you prefer a clean, linear history, you might favor git pull --rebase over a merge commit every time you pull. You can make this the default:

git config --global pull.rebase true

This is a game-changer for many developers who love a tidy commit history.

4. More Powerful Features and Hidden Gems

Now for the really fun stuff! These are some of the lesser-known settings that can solve common frustrations and make you look like a Git wizard.

  • --force-with-lease: The Safer Force Push. You probably already know git push --force is dangerous. A safer alternative is --force-with-lease, which will fail if someone else has pushed to the branch in the meantime. Make it an easy-to-use alias:

    [alias]
      pf = push --force-with-lease
  • Better Diffs: You can tell Git to use a different algorithm for calculating diffs, which can sometimes produce more readable results.

    git config --global diff.algorithm patience

    These are the available algorithms:

    • myers: The default algorithm (fast, but may produce confusing diffs).
    • patience: Slower, but often more human-readable.
    • minimal: Aims to generate the smallest possible diff.
    • histogram: An improvement over patience (faster, with similar quality).
  • blame.ignoreRevsFile: Ignoring Formatting Commits: Ever run git blame only to find that a massive reformatting commit is "blamed" for every line? As explained in more detail here, you can tell Git to ignore these commits! Create a file named .git-blame-ignore-revs with the commit hashes to ignore, and then run:

    git config blame.ignoreRevsFile .git-blame-ignore-revs
  • help.autocorrect: For the Typo-Prone Developer: Do you ever type git chekcout? Git can automatically correct your typos and run the right command for you. In the example below, the value of 10 represents 10 deciseconds, which is equivalent to 1 second.

    # Waits 1 second (10 deciseconds) before running the corrected command
    git config --global help.autocorrect 10
  • rerere: Reuse Recorded Resolution: If you find yourself resolving the same merge conflicts over and over (especially in long-lived feature branches), rerere is your new best friend. It stands for "Reuse Recorded Resolution" and you can learn more about it in this blog post.

    git config --global rerere.enabled true

    Once enabled, Git will remember how you resolved a conflict. The next time it sees the exact same conflict, it will resolve it for you automatically!

5. Performance Tuning for Large Repositories

Working in a massive monorepo? Does git status take forever? These performance-oriented settings, many of which are covered in our detailed guide to Git performance, can make a world of difference.

  • The Commit Graph: This feature dramatically speeds up history-traversing operations like git log.

    git config --global core.commitGraph true
    git config --global gc.writeCommitGraph true
    git config --global fetch.writeCommitGraph true
  • Filesystem Monitor (fsmonitor): This is perhaps the biggest performance booster for large repos. It uses a background process to watch for file changes, making commands like git status nearly instantaneous.

    git config --global core.fsmonitor true
  • The Untracked Cache: Works with fsmonitor to speed up how Git finds new, untracked files.

    git config --global core.untrackedCache true

For more tips on repository performance, you should really consider reading our in-depth article on the topic.

6. Security and Best Practices

Finally, let's look at some settings that enhance security and help you manage different contexts.

  • Signing Your Commits: You can sign your commits with a GPG key or SSH to verify your identity. This is great for open-source work and corporate environments.

    git config --global user.signingkey <YourGPGKeyID>
    git config --global commit.gpgSign true
  • Conditional Includes: This is one of the most powerful "hidden gems". includeIf lets you use different configurations based on the repository's path. This is perfect for managing work and personal projects.

For example, you can use your work email for all repositories inside ~/work/:

# In ~/.gitconfig
[user]
    name = Bruno Brito (Personal)
    email = bruno.personal@gmail.com

[includeIf "gitdir:~/work/"]
    path = ~/.gitconfig-work

Then, in ~/.gitconfig-work:

[user]
    name = Bruno Brito (Tower)
    email = bruno@git-tower.com

Now, Git will automatically use the correct name and email depending on where your repository is located!

A Recommended .gitconfig Template

Feeling inspired? Here’s a template you can use as a starting point for your own awesome .gitconfig:

[user]
    name = Your Name
    email = you@example.com

[init]
    defaultBranch = main

[core]
    editor = code --wait
    autocrlf = input
    fileMode = false
    fsmonitor = true
    untrackedCache = true

[color]
    ui = auto

[pull]
    rebase = true

[rerere]
    enabled = true

[help]
    autocorrect = 10

[alias]
    co = checkout
    ci = commit
    st = status
    br = branch
    lg = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
    pf = push --force-with-lease

# Use work email for repos in the ~/work/ directory
[includeIf "gitdir:~/work/"]
    path = ~/.gitconfig-work

Final Words

And there you have it! From simple aliases to powerful performance tuning, you're now equipped to create a Git configuration that works for you, not against you.

Don't be afraid to experiment and find the settings that best fit your workflow. A well-crafted .gitconfig is a sign of a true Git artisan! 😎

For more tips, don't forget to sign up for our newsletter below and follow Tower on Twitter and LinkedIn!

]]>
Tower 15 for Mac — Automatic Branch Management https://www.git-tower.com/blog/tower-mac-15 https://www.git-tower.com/blog/tower-mac-15 Thu, 20 Nov 2025 00:00:00 +0000 Tower 15 for Mac is here! This update introduces Automatic Branch Management, making it easier than ever to keep your repository tidy and clutter-free. We've also added significant improvements to the "History" view for better visualization of your work 😎

If you’ve ever felt overwhelmed by a cluttered sidebar full of old, merged, or long-forgotten branches, this release is for you! We know that managing a growing number of branches can be a real headache, distracting you from your main task: committing great code.

Tower 15 takes the burden of branch hygiene off your shoulders, allowing you to automatically or manually archive branches that are no longer needed.

All right, let's dive into what's new!

For a quick walkthrough of what's new, check out our 3-minute video tour below:

New "Fully Merged" and "Stale" Badges and Hint Views

The first thing you will likely notice after updating Tower is a new set of badges in the "Branches" section of the sidebar.

Tower 15 – New
Tower 15 – New "Fully Merged" and "Stale" badges


You will see new badges next to branches indicating if they are "Fully Merged" (meaning all their commits have been integrated into a primary branch) or the time they were last updated when they became "Stale" (meaning they haven't seen any activity for a while).

These badges are complemented by a helpful hint view that appears when you select a fully merged or stale branch. This view provides a quick, one-click option to delete the branch, making the cleanup process a breeze!

Tower 15 –
Tower 15 – "Fully Merged" and "Stale" Hint Views for quick deletion

Automatic Branch Management

While deleting a stale or fully merged branch is often a good choice, sometimes all you want is to hide a branch from sight.

This is now possible with Tower 15 for Mac. You will notice a new "Archived Branches" view where you can:

  • drag and drop any branch into this section.
  • add any branch to this section by clicking on the context menu.
Tower 15 – Archive Branches


You can perform this process manually (you can even select multiple branches at once!) or allow Tower to automatically identify and handle them for you.

If you choose the latter, you have two options: either click on the notification number in the footer, as shown in the example below…

Tower 15 – Automatically Archive Branches


…or enable this option by going to the Settings. In the "General" tab, you will find a new option labeled "Automatically archive stale and fully merged branches."

Tower 15 – Automatically Archive Branches in Tower's Settings
Tower 15 – Automatically Archive Branches in Tower's Settings


At any time, you can move a branch from the "Archived Branches" view back to the main "Branches" view by right-clicking on it and selecting the "Unarchive [BRANCH]" option.

Tower 15 –
Tower 15 – "Unarchive Branch" option


As you can see in the screenshot above, we've also added a "Skips Auto-Archiving" flag that allows you to keep a branch and prevents it from being automatically archived. This will also be the case for branches that you have pinned.

Fork Point: See What's Unique

Tower 15 also introduces a key visualization enhancement to help you understand your branch structure instantly.

The "History" view now clearly shows the Fork Point, which is the exact commit where a branch diverged from its parent. Commits prior to this divergence will be shown grayed out.

Tower 15 – New
Tower 15 – New "Fork Point"


If there are no exclusive commits to a branch yet, this will also be easily noticeable by the "No new commits on this branch" message.

Tower 15 –
Tower 15 – "No new commits on this branch" message


This visual improvement makes it much clearer to see exactly which commits were introduced by the branch you are currently viewing relative to its parent branch. No more guessing — just a clean, visual representation of your branch's scope.

macOS 26 Tahoe Support

As you know, we are always dedicated to offering the best experience on the Mac platform. We're happy to report that Tower 15 is fully compatible with the new operating system, macOS 26 Tahoe.

Here it is in all its glory!

Tower 15 in macOS 26 Tahoe
Tower 15 in macOS 26 Tahoe


With Tahoe, a new theming system has been implemented. This means Tower 15 now includes a set of shiny new icons!

To try them out, go to macOS's "System Settings > Appearance" and have a look at the "Icon & Widget style" section.

New Tower 15 icons in macOS 26 Tahoe
New Tower 15 icons in macOS 26 Tahoe

Other Improvements

As usual, we took some time to implement improvements across the board. We revamped the sidebar footer, which now features a collapsible filter field and allows you to choose from several view settings.

Tower 15 – Revamped Footer
Tower 15 – Revamped Footer


There is also a long list of other enhancements, most notably around the Pinned Branches feature to make it more robust and convenient:

  • Pinned Branches: Pinned branches are now stored in the Git config and should not unpin anymore, ensuring your favorites always stay put.
  • Pinned Branches: You can now pin and unpin multiple branches at once, saving you time.
  • Pinned Branches: The "Pinned Branches" section in the sidebar is now automatically expanded for quick access.
  • Pinned Branches: Undoing a branch delete now correctly restores the pinned flag.
  • Sorting: Text is now sorted in many views using a localized standard compare to match system behavior across your Mac.
  • Commit Signing: Tower now correctly handles SSH keys without a comment.
  • Settings: Ref related view settings have been moved into the View menu.

We also fixed some bugs! Here is what we addressed:

  • Merge/Rebase: Tower could crash when using Quick Merge or Rebase. This has been fixed.
  • History: A crash could occur when searching for whitespaces. This is fixed now.
  • Worktrees: In some cases Tower could crash when accessing worktrees. It's working now.
  • git-flow-next: Updating the workflow would crash in bare repositories. Not anymore.
  • Working Copy: Some actions would crash when finishing, which is fixed now.
  • Main Window: Tower could crash in certain cases when switching to a different repository in the same window. This has been fixed.
  • Reset Revision: The text field did not allow entering arbitrary revisions anymore. It does allow them again now.
  • Merge Conflict: The merge conflict wizard now allows resolving a "both deleted" conflict again.
  • Merge Conflict: A crash has been fixed that sometimes occurred when a merge tool finished.

We hope you enjoy this release! Happy committing! 😊

Not a Tower user yet? Download our 30-day free trial and experience a better way to work with Git!



PS: Did you know? Tower Pro is now free for students as well as teachers and educational institutions!

]]>
Tower 10 for Windows — Introducing Graphite Support https://www.git-tower.com/blog/tower-windows-10 https://www.git-tower.com/blog/tower-windows-10 Thu, 20 Nov 2025 00:00:00 +0000 The wait is over: Tower 10 has arrived! For enthusiasts of Stacked Pull Requests, this release is a game-changer. We're excited to announce comprehensive support for Graphite, integrating its most powerful features directly into Tower. You can now handle your stacked branches and craft Pull Requests seamlessly within our Git client ✌️

With our Tower 8.0 update, we set the stage for incorporating advanced Git workflows. Features like Branch Dependency and the "Restack" action were introduced, and the response from our user community has been overwhelmingly positive.

Building on that foundation, Tower 10 now offers full support for Graphite's toolset, empowering you to merge changes into your projects faster than ever.

This article will guide you through the essentials of Graphite and how it integrates with Tower 10.

About Graphite

If you want to enhance your team's Pull Request process and are unfamiliar with Graphite, you're in for a treat!

Graphite employs a stack-based methodology that allows developers to work on several features in parallel by layering changes. This is often called the Stacked Pull Requests workflow.

The idea is straightforward: by linking smaller, incremental Pull Requests, you reduce the amount of code to be reviewed. This leads to quicker integration and minimizes the chances of significant merge conflicts or bugs.

Effective branch management is key to this approach, and this is where Graphite excels. Even if you are the sole user of this workflow in your team, it works flawlessly from the get-go. There's every reason to give it a shot! 😉

Graphite not only simplifies branch management but also provides a dedicated interface for code reviews (be sure to check out AI Reviews!) and complements GitHub by extending its functionality.

In addition to its Web UI, Graphite provides:

You can discover more about Graphite in this article. We believed that integrating these capabilities into a Git client would be a great advantage, so we went ahead and did just that.

Let's start the tour!

Setting Up Graphite in Tower 10

To begin, simply click the "Workflows" button in the toolbar and select the new Graphite.dev entry. You will need a Graphite.dev account and the Graphite CLI tool (version 1.5.3 or higher) installed.

Tower 10 – Enabling the Graphite Workflow

☝️ You may find the "Configure Workflow" button greyed out if you haven't configured Graphite yet. Make sure you install the CLI tool and configure the Graphite token by accessing Tower's terminal ("File -> Open in Terminal").

You'll be asked to specify the "Trunk" branch (typically main) and your Graphite token, which should be detected automatically by Tower. We recommend installing the Graphite binary via npm , the standard package manager for Node.js.

You'll notice the "Workflows" icon has changed to Graphite. Clicking it gives you quick access to popular Graphite commands and opens the Graphite dashboard in your browser.

Tower 10 – Graphite Workflow in Toolbar
Tower 10 – Graphite Workflow in Toolbar


Working with Graphite in Tower 10

Now is a great time to explore the Graphite commands you can run effortlessly in Tower!

Working Copy

With the Graphite workflow active, you'll see new options in the "Working Copy" view.

We've introduced a "Create" action that lets you instantly make a new branch with your staged changes (equivalent to gt create in the Graphite CLI). This is a best practice in the Graphite workflow, which recommends treating each branch as a small, atomic changeset with a single commit initially.

The "Commit" action is similar to the gt modify --commit command in Graphite: it adds a new commit to the current branch and automatically restacks if there are no conflicts.

Tower 10 —
Tower 10 — "Working Copy" view

☝️ Tower's "Quick Amend" feature is also compatible with the Graphite workflow. To amend the current branch's commit, hold down (Left Alt + CTRL), and the "Commit" button will change to "Modify". This is the same as running gt modify in the Graphite CLI.

Creating a Stacked Branch

Graphite is centered around Stacked Branches, and creating a new one is simple: right-click on any branch to create a new stacked branch based on it.

Tower 10 — Create New Stacked Branch
Tower 10 — Create New Stacked Branch


In the following dialog, you can choose its parent branch for straightforward integration and opt to check it out right away.

Tower 10 — Create New Stacked Branch Dialog
Tower 10 — Create New Stacked Branch Dialog


From the context menu, you can also perform all other standard Graphite operations, like renaming, merging, squashing, or deleting branches.

Tower 10 – Additional Context Menu Options
Tower 10 – Additional Context Menu Options

Setting the Parent Branch

You can change a branch's parent at any time, just as you would with Stacked Branches, by using the context menu and selecting "Track Parent Branch."

In Graphite's terminology, this is known as "tracking" (gt track) and "untracking" (gt untrack) a stacked branch.

Tower 10 – Setting the Parent Branch
Tower 10 – Setting the Parent Branch

Restacking

Restacking syncs all changes by rebasing each child branch onto its parent. Tower shows an icon in the sidebar for branches that need restacking. You can perform this action by right-clicking the branch and choosing "Restack [Branch]".

In the branch's history, a yellow banner will also inform you that the branch needs to be restacked.

Tower 10 — Restack Branch
Tower 10 — Restack Branch


In the "Restack Branch" dialog, you'll see a "Restack Full Stack" option. If this is not checked, Tower/Graphite will restack the selected branch and its parents. If checked, the branch's children will also be restacked (hence "full stack").

Tower will let you know if any conflicts occur during the restack.

Tower 10 — Restack Branch Dialog
Tower 10 — Restack Branch Dialog

Syncing a Branch

Right-clicking any branch also lets you "sync" it. This synchronizes all branches in the stack, much like the gt get command.

Tower 10 — Sync Branch Dialog
Tower 10 — Sync Branch Dialog


Tower also offers extra options, like restacking all branches in your repository.

Submitting a Branch (To Create a Pull Request)

You can submit a branch to create a PR by right-clicking it and selecting the option from the context menu.

More options are available by clicking the drop-down arrow, such as updating only branches with existing open PRs.

Tower 10 — Submit Branch to Graphite
Tower 10 — Submit Branch to Graphite


All open Pull Requests are accessible in Tower's "Pull Requests" view, in the sidebar or via the shortcut CTRL + 4.

Tower 10 — Pull Requests
Tower 10 — Pull Requests


This view lets you inspect, merge, close, comment on, or check out pull requests without opening a browser.

Merge Queue

Graphite includes a Merge Queue feature that avoids semantic merge conflicts by automating the rebase process during merges. This keeps the trunk branch "green" and helps development teams move faster with fewer interruptions.

In Tower, if a merge is possible, the Graphite branch is added to the merge queue. The merge is asynchronous, so you'll need to manually refresh and sync the branch to see if it has been merged.

When a Graphite branch is sent to the merge queue, it's validated remotely. If it can be merged, it is; otherwise, the process fails.

To do this, right-click the branch and choose "Add [BRANCH] to Merge Queue…" from Tower's context menu.

Tower 10 — Graphite's Merge Queue
Tower 10 — Graphite's Merge Queue

Warning Messages

While using Tower, you might accidentally disrupt Graphite's state with certain Git operations, like a git push.

Tower will warn you when this might happen before you proceed.

Tower 10 — Warning Message
Tower 10 — Warning Message


You can enable or disable these prompts in the "Integration" tab of Tower's Settings.

Tower 10 — Integration Settings
Tower 10 — Integration Settings

Other Improvements

As always, we've also made some other improvements under the hood.

Here's a list of the improvements and bug fixes we've addressed:

  • System Menu: The Alt + SPACE shortcut now works as expected.
  • Submodules: Navigation through nested submodules has been refined.
  • Portable Git has been updated to version 2.51.2 for improved compatibility and performance.

We hope you enjoy this release! Happy stacking! 😊

Not a Tower user yet? Download our 30-day free trial and see a better way to work with Git!




PS: Did you know? Tower Pro is now free for students and teachers and educational institutions!

]]>
Version Control in the Age of AI: The Complete Guide https://www.git-tower.com/blog/version-control-in-the-age-of-ai https://www.git-tower.com/blog/version-control-in-the-age-of-ai Wed, 12 Nov 2025 00:00:00 +0000 With the rise of AI coding assistants like Claude Code and Gemini CLI, our development workflows are changing at a rapid pace. These tools can be incredibly powerful, but they also introduce new challenges. How do we maintain a clean, understandable, and efficient version control history when a significant portion of our code is generated by AI?

This article will provide a practical guide for developers to effectively use Git and version control in the age of AI. Whether you're a "vibe-coder" or a seasoned software engineer or web developer, we believe this guide can teach you something valuable to apply to your daily workflow.

We will first cover the fundamentals of Git and then explore some more advanced techniques, such as Git Worktrees, to help you maintain control of your project's advancements and keep your version control history clean and organized.

Along the way, we will also explain how Tower, our Git client, can assist you!

The Importance of Creating Snapshots of Your Project

When working with AI-generated code, it's easy to get carried away and end up with large, monolithic changes. This is where the discipline of creating frequent, small commits becomes your best friend.

Think of each commit as a snapshot of your work — a safety net that you can always go back to. If an AI-generated change introduces a bug or takes you down the wrong path, you can easily revert to a previous state. Tiny, atomic commits make it much easier to pinpoint where things went wrong.

In the upcoming chapters, we will explore a variety of techniques — both basic and advanced — that will help you keep track of your code developments.

The Fundamentals of Git

Let's start by revisiting some core Git best practices that are more important than ever in the age of AI: crafting effective commit messages and efficiently managing branches.

☝️ If you're just getting started with Git, we recommend exploring our Learn section, where you'll find a variety of free resources to help you become confident with version control, including ebooks and videos.

Crafting the Perfect Commit Message

A well-crafted commit message is a love letter to your future self and your teammates. When working with AI, it's crucial to explain the "why" behind a change, not just the "what". The AI can generate the code, but it can't (yet) understand the business context or the problem you're trying to solve.

A good commit message should be clear, concise, and descriptive. It should explain the intent behind the change and any trade-offs that were made.

This is such an important topic that we have dedicated an entire article to it!

How Tower Can Help 🔥

Tower has lots of features to help you create better commits. Here are some tips!

  1. While writing a commit in the "Working Copy" view, press / to easily reference files, commits, or even insert an emoji (Tower supports Gitmoji). If you have a service account like GitHub connected, you can also easily address an issue.
Composing Commits in Tower


  1. If your team follows specific guidelines, adhering to commit templates will make a lot of sense. The tip mentioned above allows you to follow a commit template, and you can also click the button next to the character counter to insert a template. To create, edit, or delete commit templates, visit the "Templates" tab in the Settings.
Managing Commit Templates in Tower

Branching Strategies

Feature branches are the cornerstone of a healthy Git workflow. They allow you to work on new features or bug fixes in isolation without affecting the main branch. This is especially important when experimenting with AI-generated code.

Create a new branch for each new task, and only merge it back into the main branch when you're confident that the code is working as expected.

How Tower Can Help 🔥

With its visualization capabilities, Tower lets you quickly explore any branch by viewing the list of branches in the sidebar. But a lot more can be achieved here!

  1. Tower is aware of the parent branch; therefore, if the main branch has received an update, you can quickly update your feature branch to incorporate the latest changes.
Tower's
Tower's "Update Branch" feature


  1. The "Fork Point" feature in Tower will display the precise commit at which a branch split from its parent. Commits that occurred before this divergence will appear grayed out.
Tower's
Tower's "Fork Point"


  1. Our newly released Tower Workflows feature allows you to easily create new branches and merge/clean them up when you're finished. It was designed with flexibility in mind, enabling you to customize how the feature works to suit your needs.

Advanced Git Techniques for AI-Powered Development

Now that we've covered the basics, let's explore some advanced Git techniques that are particularly well-suited for working with AI.

Staging Chunks and Lines for Granular Commits

AI-generated code often comes in large blocks. Instead of committing the entire block at once, it's a good practice to review the changes and stage them in smaller, logical chunks.

How Tower Can Help 🔥

Tower's "Changeset" view allows you to do just that. Instead of typing git add -p in the command line, you can stage individual lines or chunks of code with a single click.

This gives you granular control over what goes into each commit, helping you create those small, atomic commits we talked about earlier.

Tower's single-line staging feature

Interactive Rebase for a Clean History

AI assistants can sometimes be a bit "chatty," generating a lot of small, incremental changes. While this is great for experimentation, it can lead to a cluttered commit history.

This is where interactive rebase comes into play. Interactive rebase allows you to rewrite your commit history before merging a branch. You can reorder, squash, and edit commits to create a clean and logical history.

Before pushing your changes to the remote repository, it is always advisable to take some time to organize your commits — for your future self and your team!

Squashing is great if you prefer to move forward carefully in small steps. You can continuously add small commits labeled as "WIP" (Work in Progress) and then combine them all into a single commit when the feature is complete.

How Tower Can Help 🔥

Instead of using the command line (git rebase -i), Tower makes interactive rebase as easy as dragging and dropping:

  1. You can reorder commits by dragging them up or down in the "History" view. Tower's drag and drop feature is very capable!
  2. You can edit commit messages or the content of the commits by right-clicking a commit and selecting "Edit commit message of [COMMIT]" or "Edit [COMMIT]," respectively.

If you choose the latter option, Tower will check out that commit and allow you to make any desired changes, such as staging additional files or removing existing ones.

Editing a Commit in Tower
Editing a Commit in Tower


  1. You can also simply drag one commit onto another to squash them together (hold to fixup commits instead).
Tower – Interactive Rebase with Drag and Drop


And speaking of "fixup," you can also make amendments by typing fixup! followed by the appropriate commit in the commit message area. After that, you can access the branch view to use the "autofixup" feature.

Tower – Autofixup

Git Worktrees for Running AI Agents in Parallel

In the AI coding landscape, it's common to work on multiple features in parallel with your preferred coding agent. If that describes you, then Git worktrees are the way to go! ✌️

A worktree is a separate working directory linked to your main repository. This allows you to have multiple branches checked out simultaneously, each in its own directory.

For example, you can have your main feature branch checked out in one worktree and a hotfix branch in another. You can switch between them seamlessly without needing to stash or commit your changes, making it ideal for running multiple AI coding agents simultaneously.

How Tower Can Help 🔥

In Tower, working with worktrees is a breeze. You can create a new worktree by right-clicking on any branch in the sidebar and selecting "Check out [BRANCH] in New Worktree...".

Creating a New Worktree from a Branch
Creating a New Worktree from a Branch


The "Worktrees" section in the sidebar will help you keep track of all your worktrees.

Worktrees in Tower's Sidebar
Worktrees in Tower's Sidebar

Stacked Branches for Incremental Work

Stacked branches are useful for organizing incremental work with AI agents. For example, instead of creating multiple independent branches for a feature (such as the model and the UI), you can use stacked branches to easily update the dependent branch with any changes.

This approach also makes the final review process easier, aligning with its intended design. This is also known as the Stacked Pull Requests workflow.

How Tower Can Help 🔥

Tower allows you to create stacked branches from any branch by simply right-clicking on a branch and selecting the appropriate option from the context menu.

Tower – Create New Stacked Branch
Tower – Create New Stacked Branch


Since Tower tracks the parent branch, you will be prompted to restack the child branch whenever the parent undergoes changes, ensuring that they remain in sync. You will also be notified if any merge conflicts arise while integrating the new changes.

This even works if you are a Graphite user.

Branch Restacking in Tower

Conclusion

AI is transforming the way we write software. With code generation now possible in seconds, having a clear understanding of your project's history is more important than ever.

By adopting the principles discussed — such as making frequent, atomic commits and utilizing advanced techniques like interactive rebase and Git Worktrees — you can make your version control system the most reliable component of your AI-powered workflow.

We hope you found this guide useful! For more Git tips and tricks, don't forget to sign up for our newsletter below and follow Tower on Twitter / X and LinkedIn! ✌️

]]>
7 CLI Tools Every Developer Should Install https://www.git-tower.com/blog/7-cli-tools-every-developer-should-install https://www.git-tower.com/blog/7-cli-tools-every-developer-should-install Wed, 15 Oct 2025 00:00:00 +0000 In this post, we will have a look at 7 essential command-line tools that I believe every developer should consider adding to their arsenal. I will share why I think they're useful and provide some tips and commands to help you get the most out of them.

All right, get your terminal ready and let's get right into it! 😎

In a hurry? Watch our brief 2-minute vertical video that introduces all the tools listed below.

1. btop: A Beautiful System Resource Monitor

When you need to keep an eye on your system's performance, btop is my go-to tool. It's similar to programs like htop and atop, but in my opinion, it's much more pleasing to the eye!

Btop - A Beautiful System Resource Monitor
Btop - A Beautiful System Resource Monitor


Btop provides a comprehensive overview of your CPU, memory, disk I/O, network usage, and running processes. It is great to spot resource hogs, as it allows you to quickly sort processes by various metrics (CPU usage, memory usage, PID, etc.).

You can use the arrow keys to navigate between different sorting columns, such as memory or CPU, and then press r to sort them by that column. You can also filter a process by pressing f and then typing its name.

Btop comes bundled with dozens of themes as well! Just press Esc to access the options, where you can customize many visual aspects of the application.

2. Ncdu: Your Disk Usage Detective

Ever found yourself wondering where all your disk space went? Ncdu is a really fast disk usage analyzer that will quickly pinpoint the culprits.

Ncdu: Your Disk Usage Detective
Ncdu: Your Disk Usage Detective


Ncdu scans your directories and presents a hierarchical view of disk usage, making it incredibly easy to identify large files and folders. More importantly, it allows you to delete unnecessary items directly from its interface, saving you precious disk space and time. This is particularly handy for cleaning up large node_modules folders, old logs, or forgotten project artifacts.

Navigating through directories is easy: just use the arrow keys to move up and down. When you find a file or directory to delete, simply press the D key. Keep in mind that Ncdu will ask for confirmation before deletion, but once it's gone, you won't find the files in the Trash!

BTW, you can exclude folders with many files to speed things up. Simply type ncdu --exclude ~/Sites to exclude the "Sites" directory, for example.

3. fd: The Lightning-Fast File Finder

find is powerful, but fd is fast, user-friendly, and often exactly what you need. It's a simpler, quicker alternative for finding files in your filesystem.

fd: The Lightning-Fast File Finder
fd: The Lightning-Fast File Finder


fd is designed for speed and convenience. You can run it from a high-level directory without waiting, making it perfect for large codebases or for quickly locating a file when you know its name, even partially, but have no idea which folder it is in.

You can easily filter by file type using the command: fd --extension psd. In this example, you will see a list of available Photoshop files.

4. git-flow-next: Supercharging Your Git Workflow

If you enjoy branching workflows like Gitflow, then git-flow-next is worth exploring. It is fully compatible with the original Gitflow but includes powerful features, such as the ability to:

  • Create custom branching configurations from scratch.
  • Keep branches in sync with their parent branches by simply typing git flow update.
git-flow-next: Supercharging Your Git Workflow
git-flow-next: Supercharging Your Git Workflow


Once you define your own branching configuration (or use a preset — you can choose between the classic Gitflow, GitHub Flow, and GitLab Flow and then customize them), you can quickly start and finish branches to integrate their changes and delete fully merged branches.

Oh, BTW: `git-flow-next is an open-source project developed by the Tower team 😉

5. z: The Smart Directory Jumper

Tired of typing out long paths to frequently accessed directories? z is a brilliant tool that learns your habits and lets you jump to any directory with just a few keystrokes.

z: The Smart Directory Jumper
z: The Smart Directory Jumper


z keeps track of the directories you visit most often (based on "frecency" - a combination of frequency and recency). Instead of typing cd ~/projects/my-awesome-app/src/components, you can simply type z components or z my-awesome.

It's a massive time-saver for anyone who navigates their filesystem frequently!

6. Zellij: The Customizable Terminal Multiplexer

In an age where AI assistants like Claude and Gemini CLI are often used directly in the terminal, a robust terminal multiplexer is non-negotiable.

Terminal multiplexers allow you to run multiple terminal sessions within a single window, detach from them, and reattach later. This means you can keep your development environment running even if you close your terminal or lose your SSH connection.

While tmux is way more popular, Zellij offers a fantastic out-of-the-box experience with incredible customization. Zellij provides a clean, well-designed interface for managing panes and tabs, and its plugin system allows for powerful extensions.

Zellij: The Customizable Terminal Multiplexer
Zellij: The Customizable Terminal Multiplexer


To get started, simply type zellij -s your-saved-session to create a new session. If you detach from the session, you can later resume it by typing zellij attach your-saved-session.

You can also view your entire list of sessions by typing zellij list-sessions.

7. ASDF: The Universal Runtime Version Manager

Managing multiple versions of Node.js, Python, Ruby, or any other runtime can be a headache. ASDF simplifies this by providing a single, consistent interface for managing all your runtime versions.

ASDF: The Universal Runtime Version Manager
ASDF: The Universal Runtime Version Manager


Instead of installing separate version managers (like nvm for Node.js, rbenv for Ruby, pyenv for Python), ASDF consolidates them all. You can easily switch between different versions globally or on a per-project basis, preventing conflicts and ensuring your projects run with the correct dependencies.

To get started, install a plugin (such as Node.js or Ruby) by typing, for example, asdf plugin add nodejs. Then, you can easily install a specific version of a runtime by typing something like asdf install nodejs 22.14.0.

To set a global default version for a runtime, type asdf global <plugin-name> <version>. For a project-specific version, type asdf local <plugin-name> <version> instead; a .tool-versions file will be created in your current directory.

Finally, you can type asdf list to see a list of all the installed versions for the runtimes of your choosing.

We hope you enjoyed this list of CLI tools! Once you take some time to familiarize yourself with them, I think your experience using the terminal will be much more enjoyable!

For more tips and tricks, be sure to sign up for our newsletter below and follow Tower on Twitter / X and LinkedIn! ✌️

]]>
git-flow-next: The Next Iteration of Advanced Git Workflows https://www.git-tower.com/blog/git-flow-next https://www.git-tower.com/blog/git-flow-next Thu, 18 Sep 2025 00:00:00 +0000 Today, we're excited to introduce git-flow-next, a brand-new, open-source command-line tool that reimagines the popular git-flow model. It's designed to give you the agility and advanced capabilities needed for modern, demanding Git workflows.

As the creators of Tower, we worked closely with a lot of teams using git-flow. We understood why it was so popular, but we couldn't ignore the friction and frustration it often caused.

Instead of merely working around these problems, we decided to address them directly. While developing the Tower 14 for Mac release, which enables you to create custom branching workflows of any kind, we considered whether we could extend similar functionality to CLI users.

Tower 14 for Mac – Branch Workflow Configuration
Tower 14 for Mac – Branch Workflow Configuration


With git-flow-next, we're doing just that! We're giving back to the development community a tool that adapts to the Git workflow you're seeking – regardless of complexity and the level of flexibility you require.

Here's a 5-minute video that will guide you through all the capabilities of git-flow-next:

Core Features

git-flow-next was built on top of the original git-flow and gitflow-avh projects (both of which are now discontinued), paving the way forward with a strong emphasis on improving the developer experience and making it much more customizable.

In short, our aim is to deliver a tool that is:

  • Engineered for stability and flexibility.
  • Written in Go for exceptional speed and efficiency.
  • Fully compatible with your existing git-flow setups.
  • Able to provide clearer guidance through complex merges.
  • Designed to seamlessly integrate with today's diverse Git practices.

That is the TL;DR version. Below is a more in-depth look at what makes it stand out.

1. Written in Go for Better Performance

At its heart, git-flow-next is a complete rebuild using Go. This choice ensures exceptional reliability, resource efficiency, and provides a highly responsive experience.

Go's concurrent capabilities and strong type system contribute to a remarkably stable and predictable tool, while its efficient compilation delivers impressive performance.

This modern architecture guarantees git-flow-next can evolve alongside the dynamic world of software development and Git.

2. Improved Conflict Resolution

Merge conflicts are an unavoidable reality in collaborative projects.

While Git's core merge mechanism remains intact, git-flow-next offers more intuitive strategies and clear instructions during the resolution process, enabling teams to navigate merges with newfound confidence and minimal disruption.

3. Your Workflow, Your Way

Understanding that no two development teams are alike, git-flow-next offers unparalleled configuration flexibility. This is a big step compared to the conventional workflow imposed by the original git-flow model.

You can come up with your own branch naming conventions to match your team's preferences and current infrastructure. Beyond that, you can take control of merge strategies, fine-tuning how branches are integrated based on your project's unique needs.

This adaptability ensures git-flow-next fits perfectly into a wide spectrum of development workflows.

4. Smooth Adoption

Adopting new tools shouldn't force a complete overhaul. git-flow-next is meticulously crafted for full compatibility with your existing git-flow repositories.

You can effortlessly switch to git-flow-next without re-initializing repositories or disrupting your team's established processes. This backward compatibility guarantees a smooth adoption and empowers teams to incrementally embrace the advantages of git-flow-next.

5. Clear Guidance Through Any Hurdle

Not everyone is a Git nerd, and we're OK with that. git-flow-next prioritizes a frictionless developer experience by providing clear and actionable error messages.

When issues arise, the tool offers clear guidance and practical solutions for recovery, ensuring you spend less time troubleshooting and more time coding.

Get Started… and Get Involved!

We're incredibly enthusiastic about git-flow-next and believe it will become a great tool for developers seeking a modern, flexible approach to their Git workflows.

We encourage you to test it out and see for yourself! To get started, simply follow the installation steps in the official documentation.

As an open-source project, you can find the git-flow-next repository on GitHub. We'd love to see you contribute and take this project even further!

To stay updated on the latest git-flow-next and Tower releases, be sure to sign up for our newsletter below and follow Tower on Twitter / X and LinkedIn! ✌️

]]>
Tower 14 for Mac — Custom Git Workflows https://www.git-tower.com/blog/tower-mac-14 https://www.git-tower.com/blog/tower-mac-14 Tue, 19 Aug 2025 00:00:00 +0000 Tower 14 for Mac is here! This update allows you to create custom Git workflows, enabling you to define and enforce the exact workflow that meets your project's needs.

We have spoken with many teams and learned that most struggle to develop their own ideal Git workflows. As a result, they often end up adapting generic solutions or creating systems that are difficult for everyone to follow.

If that resonates with you, you will definitely love this release! Tower 14 for Mac puts you in the driver's seat, allowing you to define trunk, base, and topic branches, as well as set merge strategies and various other options.

Think of this as creating your own system — such as git-flow — but with limitless possibilities! 😎

All right, let's take a look at what's new – but first, let's recap why you should consider using a Git workflow if you don't have one already.

For a quick walkthrough of what's new, check out our 5-minute video tour below:

Why Workflows Matter

It is important to standardize your branching and merging practices so that you can create a predictable development environment. We feel this is key for a productive, enjoyable experience with Git, especially when collaborating with teams!

This standardization and predictability offer many advantages.

  1. Every team member can easily understand the repository's state and the purpose of each branch if you use clear naming conventions and well-defined merge behaviors.
  2. New colleagues can quickly grasp the project's specific Git conventions, leading to quicker onboarding.
  3. The entire team will become less prone to errors.

Workflows can (and should!) be automated, making this process even more beneficial to everyone — and this is exactly where Tower 14 comes in.

Setting Up a Custom Git Workflow

The heart of Custom Git Workflows lies in its flexibility. You can create a workflow tailored to your project, team size, and development methodology. They can be as simple or complex as you'd like!

The magic begins by clicking on the "Workflows" icon, now conveniently located on the left-hand side next to the "Services" and "Bookmarks" views.

Tower 14 –
Tower 14 – "Workflows" icon in the Toolbar


Here, you can set your preferred workflow by choosing from the following options:

  • Predefined workflows, such as git-flow or GitHub/GitLab Flow.
  • Other workflows like Graphite or GitFlow CLI.
  • The option to create any custom Git workflow you can imagine from scratch.

If your project already has a workflow in place, Tower will attempt to auto-detect it based on the existing branches.

Tower 14 – Select your Workflow
Tower 14 – Select your Workflow


To understand the power of this feature, let's explore an existing workflow — we will use git-flow— and break down the extensive customization options available in Tower Workflows.

Tower 14 — Branch Workflow Configuration
Tower 14 — Branch Workflow Configuration


Look at all those options! Let's explore what they can do.

The first step is to define your core branches, i.e., your "trunk" (e.g., main, master) and "base" (e.g., develop, dev) branches so that you can establish the foundational structure of your repository.

☝️ If you want to learn more about "trunk", "base", and "topic" branches, we recommend reading this article.

Afterwards, you should define your "topic" branch types (e.g., feature, hotfix, release). For each topic branch type, you can set specific branch prefixes (e.g., feature/, hotfix/). This clarifies intent and ensures consistency across your team and can be used for automated checks and organization.

In the example below, we've added bugfix to our Workflow, which is not part of git-flow by default — a prime example of the customizability of this feature.

Tower 14 – Topic Branch Configuration
Tower 14 – Topic Branch Configuration


Next, you can take full control of how changes flow through your branches. You can now define distinct downstream merge strategies (merging the parent into your topic branch to keep it up to date) and upstream merge strategies (merging a branch into its parent to finalize topic branches).

Whether you prefer merge, rebase, or squash, Tower 14 lets you dictate the exact behavior for each merge scenario.

Tower 14 — Merge Strategy Configuration
Tower 14 — Merge Strategy Configuration


When merging upstream, you can also create a tag, which can be useful for releases or significant milestones. This makes sure critical points in your project's history are always marked.

Finally, you have the option to create a merge commit when integrating branches, ensuring a complete and traceable record of all integrations. For those who prefer a cleaner, linear history, you can opt out.

Tower 14 – Configuring Merge Commit and Tag Creation
Tower 14 – Configuring Merge Commit and Tag Creation

Starting and Finishing a Feature/Hotfix/…

Once your workflow is configured, you can easily get started with your work by clicking the "Workflows" button and choosing the appropriate option.

Tower 14 –
Tower 14 – "Start Feature"


Once the task is complete, you can either click the "Workflows" button again to finish the feature, or access the branch's context menu by right-clicking the mouse.

Tower 14 –
Tower 14 – "Finish Feature" in the Context Menu

Updating Branches

While you are working on a new feature, it's normal for the parent branch to receive new commits from other team members. To minimize the chance of encountering merge conflicts, you should integrate those changes frequently.

We have good news here: this is very easy when using Tower ✌️

Since Tower establishes a parent/child relationship between branches, you will see a banner reminding you that you should update your child branches since there have been updates to the parent branch.

This feature is extremely useful for smoothly integrating your changes when you finish working on a feature or bug fix, so we recommend that you update your child branches often!

Tower 14 –
Tower 14 – "Update Branch" notification


In the update process, Tower will always inform you if there are any merge conflicts that need to be resolved.

Tower 14 –
Tower 14 – "Update Branch with Merge Conflicts" notification


You will also be notified of any conflicts in the "Update branch" dialog.

Tower 14 –
Tower 14 – "Update Branch" dialog


TIP: Don't forget to establish dependencies between branches so that child branches receive updates from their parent branches when changes occur. You can right-click any branch at any time and set a different "Upstream" or "Parent Branch" to track.

Tower 14 – Track Parent Branch
Tower 14 – Track Parent Branch


We hope you enjoy this release! Happy committing! 😊

Not a Tower user yet? Download our 30-day free trial and experience a better way to work with Git!




PS: Did you know? Tower Pro is now free for students as well as teachers and educational institutions!

]]>
Git Branching Explained: Base, Topic, and Parent Branches https://www.git-tower.com/blog/base-topic-parent-branches https://www.git-tower.com/blog/base-topic-parent-branches Tue, 29 Jul 2025 00:00:00 +0000 How do you integrate new features without breaking existing functionality? How do multiple developers work concurrently without conflicts? The answer lies in mastering Git's powerful branching capabilities.

Within Git's powerful arsenal, branches are its absolute superpower. They let you, and your team, work on new ideas, fix bugs, and experiment without causing chaos in your main codebase.

In this post, we'll take a deep dive into core Git branching concepts, showcasing why they are absolutely indispensable for stress-free software development.

Let's jump right in by first identifying and distinguishing the key branch types, so you can clearly understand their role and value for any development team:

  1. Base Branches
  2. Topic Branches
  3. Parent Branches

1. The Foundation: Base Branches

Imagine your project's main development path as the sturdy trunk of a tree, or the main highway in a bustling city. In Git, this is what we call a base branch.

A base branch is a long-lived, stable branch that represents the primary line of development for your project. You'll most commonly encounter branches named main (the modern default, replacing the older master) or develop. Think of it as the source of truth – the code that is either currently deployed to production, or is always in a deployable state.

You can have multiple base branches: a typical example is a development branch where work is done and then at some point merged into main, representing your production state that can be deployed.

💡 In a nutshell: The "Base Branch" is the long-lived, stable branch (e.g., main, develop) from which new features or fixes originate. It's the "source of truth" for the project's current state.

The base branch serves as your project's unwavering foundation. It provides a consistent and reliable reference point for everyone on the team, ensuring that there's always a known good version of the code. This stability is crucial, as you don't want experimental or unfinished features breaking what's already working.

As the main line of work lives in your base branches, they serve as essential reference points for many functionalities that determine whether work has been integrated and whether it is safe to delete a topic branch. When using commands like git branch --merged <BRANCH> or git branch --no-merged <BRANCH>, it is important to run these for every base branch to gain an overview of which branches have been merged upstream and which have not.

In an upcoming version of Tower, this information will be used to automatically identify branches that have been merged.

2. Feature Focus: Topic Branches

Now, let's say you're building a new feature, such as a user authentication system, or maybe fixing a tricky bug. You definitely don't want to mess with the stable base branch while you're experimenting!

This is where topic branches come into play.

A topic branch is a short-lived branch that you create to work on a specific feature, bug fix, or experiment. When you type something like git checkout -b new-auth-feature main, you're essentially saying, "Hey Git, create a new branch called new-auth-feature based on the current state of main, and then switch me over to it!"

The lifecycle of a topic branch is straightforward: you create it, do your work, test it, and once it's complete and reviewed, you merge it back into your base branch. After the merge, the topic branch is typically deleted, keeping your repository tidy.

💡 In a nutshell: If main is the main road, a topic branch is a temporary detour you take to work on something specific. Once you're done, you merge your changes back onto the main road.

Topic branches allow you to work on your changes in a completely isolated environment, which is clearly the main advantage of working this way. If your new feature introduces unexpected bugs or doesn't pan out as planned, it's contained within the topic branch. You can fix it there or simply discard the branch without ever affecting the stable main branch.

Topic branches also provide a sensible way to collaborate. Multiple developers can work on different features simultaneously, creating their own topic branches so they don't step on each other's toes. This approach also has its advantages when it's time to review the code before merging, often through creating pull requests. Your teammates can review your changes, offer feedback, and approve them before they become part of the main codebase.

As a bonus, this approach contributes to a clean project history, as your base branch maintains a clear, understandable, and linear history of integrated features rather than a jumbled mess of individual commits.

3. The Lineage: Parent Branches

Every branch has a history, and part of that history is its parent branch. Simply put, the parent branch is the branch from which another branch was created. It's the immediate ancestor, defining the starting point and initial state of the new branch.

Most often, when you create a topic branch like feature/shopping-cart, its parent branch will be your base branch, main or develop. The new feature/shopping-cart branch inherits all the commits and files that were present in main at the moment it was created.

💡 In a nutshell: The parent branch is the "origin" of a child branch. It's the branch whose history the new branch inherits at the moment of its creation.

This relationship determines which changes will be exclusive to your topic branch compared to its parent branch. With Tower 14 for Mac, the parent branch is selected by default when using the "Compare" view, allowing you to see only the unique commits introduced by this feature branch.

Tower 14 — Branch Comparison
Tower 14 — Branch Comparison


If you have multiple base branches, a base branch can also have another base branch as a parent. Consider our example from above (in the "Base Branches" section): your develop’s branch parent would be main, as work ultimately always flows upwards to your main branch. The other way around, if main would receive changes from e.g. hotfix branches, develop would need those changes from main in order to stay in sync.

Tower 14 makes it easy to stay uptodate with the new "Update Branch" action.

Tower 14 —
Tower 14 — "Update Branch" Action


The parent branch is usually the branch that your topic branch will be merged back into, unless you are using stacked branches (see below). In that case, the stacked branch will ultimately be merged back into the trunk branch after all stacked parents have been merged.

The Stacked Branches Workflow

While a new branch typically sprouts directly from your base branch, sometimes your work is so extensive, or involves multiple interdependent logical changes, that it benefits from a more layered approach.

This is where stacked branches, also known as "stacked pull requests", come into play.

These are a series of dependent topic branches. Instead of each new branch directly diverging from the base, they form a chain of dependencies.

It looks something like this:

The Stacked Branches Workflow
The Stacked Branches Workflow


In this scenario:

  • refactor-payment-gateway's parent is main.
  • implement-stripe-integration's parent is refactor-payment-gateway.
  • add-subscription-plans's parent is implement-stripe-integration.

Each branch in the stack represents a distinct, logically isolated chunk of work, but they are built upon, and thus dependent on, the changes introduced in the "parent" branch below them in the stack.

Stacked Branches: Pros and Cons

Let's start with the good: Stacked Branches are a great solution when you're working on large features that can be overwhelming to review. By breaking them into a stack, each pull request (PR) for a branch in the stack is smaller and easier to understand, speeding up code reviews.

This allows for faster, uninterrupted development since you don't have to wait for the first part of a large feature to be reviewed and merged before starting work on related parts. This also enables you to ship parts of a larger feature incrementally, delivering value sooner.

Stacked branches can present some challenges, most notably the need for frequent rebasing to keep them up to date with the base branch. For this reason, additional tools are often recommended.

Good news — Tower not only supports Stacked Branches but can do the restacking automatically for you! This was introduced in Tower 12 for Mac and Tower 8 for Windows.

Restacking in Tower for Mac
Restacking in Tower for Mac


Specialized tools like Graphite can simplify the management of stacked pull requests. Tower is the only Git client with Graphite support, allowing for Stacked PR management without the need of using the Graphite CLI or the browser.

You can learn all about this integration in the 5-minute video below:

Best Practices for Branching

To maximize the benefits of branching, we would like to share some advice with you, along with some helpful Tower tips!

  • Keep Topic Branches small: Focus each topic branch on a single, logical change. Smaller branches are easier to review and manage.

  • Descriptive naming is recommended: Make an effort to use meaningful names for your branches, such as feature/user-profile-edits, bugfix/login-form-validation, or hotfix/critical-api-issue.

  • Merge or Rebase frequently: Regularly update your topic branch with the latest changes from its parent (usually the base branch) to minimize complex merge conflicts later on.

With Tower, merging is as simply as dragging and dropping!

Merging a branch in Tower with Drag and Drop


Keeping topic branches up to date has become even easier with the release of Tower 14 for Mac. By setting up parent/child relationships, Tower will notify you whenever your branch needs updating; When this occurs, you can simply click the "Update Branch" action instead of manually merging or rebasing branches.

Tower 14 – Track Parent Branch
Tower 14 – Track Parent Branch


  • Always use pull requests for code review and integration: This ensures a thorough review process before changes hit the base branch.

With Tower, you can create a pull request by simply dragging and dropping the desired branch onto the "Pull Requests" workspace view.

Creating a pull request in Tower with Drag and Drop


And if you are an adopter of the Stacked Branches workflow, remember to always restack to keep your branches in sync by restacking often.

Tower 13 for Mac — Restack Branch Dialog
Tower 13 for Mac — Restack Branch Dialog


  • Delete branches after merging: Once a topic branch is merged into your base branch, delete it from your local and remote repositories to keep things clean.

In Tower's "Branches Review" view, you can filter by "Fully Merged" to pinpoint the branches that can be removed without hesitation.

Cleaning up fully merged branches in Tower

Final Words

By embracing the foundational stability of your Base Branch, the focused isolation of Topic Branches, and the logical structure provided by Parent Branches (even in complex stacked scenarios), you are setting yourself and your team up for safe experimentation, parallel feature development, and clear code reviews.

Follow these guidelines and our branching best practices to enjoy a development workflow that is more efficient, less stressful, and ultimately more productive.

For more Git tips and tricks, don't forget to sign up for our newsletter below and follow Tower on Twitter / X and LinkedIn! ✌️

]]>
Tower 9.1 for Windows — Gitea and Gitmoji Support https://www.git-tower.com/blog/tower-windows-91 https://www.git-tower.com/blog/tower-windows-91 Tue, 01 Jul 2025 00:00:00 +0000 With the release of Tower 9.1 for Windows, we're bringing the power of Gitea directly to our Git client! This means that you can now add your Gitea accounts and manage your precious repositories and pull requests without ever leaving Tower 😊

Gitea isn't the only star of the show; this release also introduces support for Gitmoji, allowing you to create more meaningful and expressive commits!

In an age where cloud services reign supreme, the idea of hosting your own code might seem a bit old-school. But for many, privacy, control, and performance are paramount. This is where self-hosted Git solutions truly shine, offering a robust alternative to public cloud providers. And among these, Gitea has emerged as a fantastic candidate.

Gitea is a lightweight, open-source, self-hosted Git service that provides everything you need for Git hosting, code review, team collaboration, and more, all within your own infrastructure.

This means complete control over your data, enhanced security, and, often, better performance tailored to your specific needs. It's also very popular among teams that simply want to avoid vendor lock-in.

☝️ If you're new to Gitea, we have prepared a quick tutorial to help you get started with Gitea on a VPS 😎

All right, let's see how you can add Gitea as a remote service to Tower and get started! If you prefer, you can also watch the 5-minute video tour below:

Adding a Gitea Account to Tower

Getting your Gitea account set up in Tower is a breeze and it works like adding any other remote service, like GitHub, BitBucket, or GitLab.

To add a new Gitea service account, simply follow these steps:

  1. Navigate to the "Remote Services" view by clicking the cloud icon in the toolbar, selecting "View > Show Services," or pressing Alt + S.
Tower 9.1 for Windows —
Tower — "Services" in the Toolbar


  1. Click on the "Gitea" or "Gitea Self-Hosted" option in the Service Accounts list, or click the "+" button in the bottom-left corner to add a new Gitea account.
Tower 9.1 for Windows —
Tower — "Gitea" and "Gitea Self-Hosted" options


  1. Tower will then prompt you for your Gitea instance URL and your credentials. Enter the full URL of your Gitea server (if self-hosted) and then provide your username and password (or better yet, a personal access token for more secure authentication).
Tower 9.1 for Windows — Add Gitea Account
Tower — Add Gitea Account


  1. Once you've entered your details, click "Add Account". Tower will verify your credentials; if successful, your Gitea account will appear in your Services list.
Tower 9.1 for Windows — Gitea Repositories
Tower — Gitea Repositories


And just like that, you're connected! All your Gitea repositories will now be accessible, ready for you to clone, fetch, and manage! 🎉

Inspecting Gitea Pull Requests in Tower

One of the most powerful features of Git is the ability to collaborate through pull requests. Gitea enables you to easily create pull requests directly in the browser, as shown below.

Creating a Pull Request in Gitea
Creating a Pull Request in Gitea


However, Tower allows you to seamlessly manage your Gitea pull requests, making code review and collaboration even more efficient — no need to open browser windows!

Once your Gitea account is added (as described in the previous chapter), open any repository and navigate to the "Pull Requests" section in Tower's sidebar, found under the "Workspace" heading.

Tower will display a list of all open pull requests for that repository. You'll see key information such as the pull request title, author, and status.

Tower — Gitea Pull Requests
Tower — Gitea Pull Requests


Click on any pull request in the list to open its detailed view. You will find 3 tabs:

  1. Conversation: View comments from your team members and reply.
  2. Commits: Browse the commit history and inspect individual file changes.
  3. Changeset: View the full diff of changes.

At the bottom, you will also have the option to check out, close, or merge the pull request, assuming you have the necessary permissions.

This functionality eliminates the constant context switching between your Git client and the Gitea web interface — it's all about staying in the flow 😎

Gitmoji Support

Gitmoji is an open-source project that aims to standardize the use of emojis in commit messages. You can learn more about it in this blog post.

While you can manually enter the necessary emojis when creating a commit, the recommended method is to use the Gitmoji CLI tool or… the latest release of Tower for Windows! 😎

Let's see it in action.

Crafting a Commit with Gitmoji

Tower supports Gitmoji without the need to install any additional tools. This feature was first introduced in Tower 10.5 for Mac and is now also available on Tower for Windows.

To include emojis in your commit message, just type :: in the "Commit Subject" field. A list of emojis will show up, along with descriptions of their meanings. You can also have a look at the complete list of emojis available here.

Tower 9.1 for Windows — Add Gitmoji
Tower 9.1 for Windows — Add Gitmoji


Gitmoji is also available in our Commit Composing tools, which you can access by simply typing /.

Tower 9.1 for Windows — Commit Composing with Gitmoji
Tower 9.1 for Windows — Commit Composing with Gitmoji


That's it! As you can see, adding the right emoji to your commit messages is quite simple.

Tower will also display the emojis in any "History" view, as shown below.

Tower 9.1 for Windows — History View with Gitmoji
Tower 9.1 for Windows — History View with Gitmoji

Other Improvements

As is tradition, we've also addressed some other small improvements and bug fixes, such as:

  • LFS: Pulling LFS repositories now works as expected.
  • Sidebar: Remote names are now accurately updated after renaming.
  • Network Paths: Fixed a potential crash when handling network paths.
  • Services: Enhanced logic for matching repositories to their configured services.
  • UI: Increased separator visibility in Dark Mode and improved visualization of parent-child branch relationships.
  • Portable Git: Updated to version 2.50.0 for improved compatibility and performance and upgraded the zip utility to support the latest compression formats.
  • Shortcuts: Reassigned the Ctrl + Shift + Backspace shortcut to the "Reset" action and removed it from "Discard All Changes", ensuring more intuitive shortcut behavior.
  • Stacked branches: Fixed an issue where the restack context menu item was incorrectly enabled, as well as an issue where, under certain conditions, the restack dialog validation could run indefinitely.

For the complete changelog, please have a look at the Release Notes.

We hope you enjoy our latest Windows release. Happy committing! 😊

New to Tower? Download our 30-day free trial and discover a more efficient way to work with Git!




PS: Did you know? Tower Pro is now free for students as well as teachers and educational institutions!

]]>
How to Install Gitea (with SQLite3 and HTTPS!) on a VPS https://www.git-tower.com/blog/how-to-install-gitea https://www.git-tower.com/blog/how-to-install-gitea Tue, 24 Jun 2025 00:00:00 +0000 Setting up your own Gitea instance on a VPS might sound daunting, but trust me, it's more straightforward than you think! By following this guide, you'll have your private Git server up and running in no time.

This is quite a fun project that offers significant benefits! By the end of this tutorial, you will have unparalleled control over your source code, your data, and your team's collaboration workflow.

Here is the plan for today:

  • Install Gitea on a VPS with a fresh Ubuntu 24.04 installation
  • Configure Gitea with SQLite 3
  • Set up HTTPS with Nginx and Let's Encrypt

So, grab your terminal, pour yourself a cup of coffee, and let's get started on bringing your Git hosting in-house.

📣 We are celebrating the Tower 9.1 for Windows release, which brings full Gitea support. This means that you can now manage your repositories and pull requests directly in our Git client!

Preparing Your VPS: The Groundwork

Before we install Gitea, we need to ensure our VPS is ready. For this tutorial, we'll assume you're using a fresh Ubuntu 24.04 LTS instance, which is a popular and stable choice.

1. Connect to Your VPS via SSH

First things first: open your terminal and connect to your VPS. Replace your_username and your_vps_ip with your actual login details:

ssh your_username@your_vps_ip

If this is your first time connecting, you might be prompted to confirm the host's authenticity. Type yes and press Enter.

2. Update Your System

It's always a good practice to update your package lists and upgrade any existing packages to their latest versions:

sudo apt update && sudo apt upgrade -y

3. Install Required Dependencies

Gitea requires Git, a database, and a few other packages. We'll use SQLite3 for simplicity in this tutorial, but for larger deployments, you might consider PostgreSQL or MySQL.

sudo apt install git sqlite3 -y

4. Create a Git User for Gitea

Gitea runs best under its own dedicated user. This enhances security by isolating the Gitea process.

adduser \
   --system \
   --shell /bin/bash \
   --gecos 'Git Version Control' \
   --group \
   --disabled-password \
   --home /home/git \
   git

This command creates a new system user named git with a home directory at /home/git.

Installing Gitea

Now that the groundwork is laid, let's get Gitea onto your server! We'll download the official binary, which is the easiest way to get up and running.

1. Download the Gitea Binary

First, please check the official Gitea documentation for the latest stable release. Look for the Linux AMD64 static binary. As of writing, the latest stable version is 1.23.8.

wget -O gitea https://dl.gitea.com/gitea/1.23.8/gitea-1.23.8-linux-amd64

Now, we will make the binary executable and copy it to a more appropriate folder: /usr/local/bin/gitea

chmod +x gitea
cp gitea /usr/local/bin/gitea

2. Create Necessary Directories

Gitea needs specific directories for its configuration, logs, and repositories.

mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git:git /var/lib/gitea/
chmod -R 750 /var/lib/gitea/
mkdir /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea

⚠️ Please note that /etc/gitea is temporarily set with write permissions so that the web installer can write the configuration file. After the installation is finished, we should change these permissions to read-only using:

chmod 750 /etc/gitea
chmod 640 /etc/gitea/app.ini

3. Create a Systemd Service for Gitea

Running Gitea as a systemd service ensures it starts automatically on boot and can be managed easily.

Create a new service file:

sudo nano /etc/systemd/system/gitea.service

Paste the following content into the file. Pay close attention to the WorkingDirectory and ExecStart paths:

[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target network.target

[Service]
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea

[Install]
WantedBy=multi-user.target

Save and exit (Ctrl + X, Y, Enter).

4.. Enable and Start the Gitea Service

sudo systemctl enable gitea
sudo systemctl start gitea
sudo systemctl status gitea

You should see output indicating that the Gitea service is active (running). If not, check the logs with journalctl -u gitea.

Initial Gitea Configuration (Web Interface)

Gitea is now running! You can access its web installer to complete the setup.

1. Access the Web Installer

By default, Gitea listens on port 3000. Open your web browser and navigate to http://your_vps_ip:3000.

You'll be greeted by the Gitea installation page. Feel free to review each field, but there's only one key setting that you should change: the Database type.

  • Database Type: SQLite3

Click "Install Gitea". This process will create the app.ini configuration file in /etc/gitea.

After the installation, it's time to register your first user, which will be the administrator account. Simply click on "Register Now" and enter a username, email address, and password.

Gitea – User Registration
Gitea – User Registration


Success! You should now have access to the Gitea dashboard! 🎉

Gitea – Dashboard
Gitea – Dashboard

Setting Up HTTPS with Nginx and Let's Encrypt

Having Gitea running is great, but accessing it via http://your_vps_ip:3000 isn't very secure or user-friendly. We want to access it via https://gitea.mywebsite.com. This requires a web server (Nginx) acting as a reverse proxy and an SSL certificate (from Let's Encrypt).

1. Point Your Domain to Your VPS

Before proceeding, make sure your domain's DNS records are set up. Create an A record for gitea.mywebsite.com that points to your VPS's public IP address. DNS changes can take some time to propagate.

2. Install Nginx

Nginx will be our web server that handles incoming requests on port 80 and 443 and forwards them to Gitea running on port 3000.

sudo apt install nginx -y

3. Configure Nginx as a Reverse Proxy

Create a new Nginx configuration file for your Gitea site:

sudo nano /etc/nginx/sites-available/gitea.conf

Paste the following configuration. Replace gitea.mywebsite.com with your actual domain.

server {
    listen 80;
    server_name gitea.mywebsite.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Save and exit.

4. Enable the Nginx Site and Test Configuration

Create a symbolic link to enable the site:

sudo ln -s /etc/nginx/sites-available/gitea.conf /etc/nginx/sites-enabled/

Test your Nginx configuration for syntax errors:

sudo nginx -t

If it reports "syntax is ok" and "test is successful", reload Nginx to apply the changes:

sudo systemctl reload nginx

Now, if you navigate to http://gitea.mywebsite.com (without the :3000 port), you should see your Gitea instance!

5. Install Certbot (for Let's Encrypt SSL)

Time for SSL! Let's install Certbot, a tool that automates obtaining and renewing Let's Encrypt SSL certificates.

sudo apt install certbot python3-certbot-nginx -y

6. Obtain and Install SSL Certificate

Now run this command, once again replacing gitea.mywebsite.com with your own domain.

sudo certbot --nginx -d gitea.selfhostfun.win

Certbot will guide you through the process interactively. It will ask for your email and require you to agree to the terms of service.

Once that is done, Certbot will automatically modify your Nginx configuration to include the SSL certificates and force HTTPS.

7. Update Gitea's Base URL in app.ini

Finally, we need to tell Gitea that it's now accessible via HTTPS. Edit Gitea's main configuration file:

sudo nano /etc/gitea/app.ini

Find the [server] section and change the ROOT_URL to your HTTPS domain:

[server]
PROTOCOL = http
DOMAIN = gitea.mywebsite.com
ROOT_URL = https://gitea.mywebsite.com/
HTTP_PORT = 3000

Note: Keep PROTOCOL = http and HTTP_PORT = 3000 because Nginx is handling the HTTPS part and forwarding to Gitea's internal HTTP port. The ROOT_URL is what Gitea uses for generating links internally.

Save and exit.

8. Restart Gitea to Apply Changes

sudo systemctl restart gitea

All Done!

Congratulations! You should now have your very own Gitea instance running securely on your VPS, accessible via https://gitea.mywebsite.com!

Gitea — Installation Complete with HTTPS
Gitea — Installation Complete with HTTPS


You've taken full control of your Git hosting, providing a private, powerful, and efficient platform for your team's code collaboration. No more relying solely on public cloud services when you have the power to host your code exactly how you want it!

With your Gitea instance up and running, you can now seamlessly integrate it with Tower for Windows 9.1, bringing all the power of your self-hosted Git repositories and pull requests right to your desktop 😎

Tower —
Tower — "Gitea" and "Gitea Self-Hosted" options


We hope you found this post helpful. For more Git tips and tricks, don't forget to sign up for our newsletter below and follow Tower on Twitter / X and LinkedIn! ✌️

]]>
Tower 13 for Mac — Introducing Graphite Support https://www.git-tower.com/blog/tower-mac-13 https://www.git-tower.com/blog/tower-mac-13 Tue, 24 Jun 2025 00:00:00 +0000 Tower 13 is here! If you are a fan of Stacked Pull Requests, "13" is indeed your lucky number! This update introduces seamless Graphite support for all the most popular actions, allowing you to manage your stacked branches and create Pull Requests without ever leaving our Git client.

Our previous major release laid the groundwork for adding popular Git workflows by introducing Branch Dependency capabilities and the "Restack" action — and many Tower users have embraced this new workflow with open arms.

Now, Tower 13 takes full advantage of this foundation to support Graphite tooling, enabling you to integrate changes into your project at a rapid pace.

In this blog post, you will learn more about Graphite and its integration into Tower 13. If you prefer, you can also watch the 5-minute video tour below:

About Graphite

If you're looking to improve the Pull Request approval process in your organization and haven't heard about Graphite yet, we think you're missing out!

Graphite provides a stack-based workflow that enables developers to work on multiple features simultaneously by stacking changes on top of each other. This approach is commonly referred to as the Stacked Pull Requests workflow.

The concept is simple: by chaining incremental Pull Requests, there is less code to review, leading to faster code integration and a reduced likelihood of introducing bugs or running into major merge conflicts.

For this approach to be successful, managing branches efficiently is paramount – and that's where Graphite shines! Even if you're the first (or only) person on your team to adopt this workflow, everything will work perfectly right away, so there's absolutely no reason not to give it a try 😉

In addition to effortless branch management, Graphite also provides its own interface for code reviews (check out Diamond — hot off the press!) and works alongside GitHub, enhancing its functionality.

Apart from the Web UI, Graphite also offers:

You can learn more about Graphite in this blog post. We thought it would be nice to integrate these features into a Git client, so we rolled up our sleeves and built just that.

Let's begin the guided tour!

Working with Graphite in Tower 13

To get started, click the "Workflow" button available in the toolbar and pick the new entry: Graphite.dev!

Tower 13 – Enabling the Graphite Workflow


☝️ Please note that you need to have a Graphite.dev account and the Graphite CLI tool installed (version 1.5.3 or higher).

You will then be prompted to define the "Trunk" branch (usually main) and enter your Graphite token (more info here) and the path to the Graphite binary.

We recommend installing the Graphite binary using homebrew, as Tower should automatically detect it. That said, Tower also supports detection via npm (the standard package manager for Node.js), so it should pick it up as well.

Tower 13 — Configure Graphite Workflow
Tower 13 — Configure Graphite Workflow


With everything set up, Tower will automatically load the branch information from Graphite by executing the command that CLI Graphite users recognize as gt state in the background.

You may have noticed that the "Workflow" icon has switched to Graphite. By clicking the button, you will be able to quickly access some of Graphite's most popular commands and open the Graphite dashboard in your browser.

Tower 13 – Graphite Workflow in Toolbar
Tower 13 – Graphite Workflow in Toolbar


All right, this is the perfect time to explore the Graphite commands that you can effortlessly run in Tower!

Working Copy

With the Graphite workflow enabled, the first thing you will notice is that there are new options available in the "Working Copy" view.

We've added a new "Create" action that allows you to instantly create a new branch with the staged changes (the equivalent of gt create in Graphite's CLI tool). This is a good practice within the Graphite workflow, as it is recommended to treat each branch as an atomic changeset containing, at least initially, a single commit.

The "Commit" action functions like the gt modify --commit command in Graphite: it adds a new commit to the currently checked-out branch and automatically restacks if necessary, provided there are no conflicts.

Tower 13 —
Tower 13 — "Working Copy" view

☝️ Tower's "Quick Amend" feature also works with the Graphite workflow. To modify the current branch by amending its commit, hold the Option key () and the "Commit" button will be renamed to "Modify". This is the equivalent of running gt modify in Graphite's CLI tool.

Creating a Stacked Branch

Graphite is all about Stacked Branches, and creating a new one couldn't be easier: just right-click on the "Branches" view in the sidebar to create a new stacked branch.

Tower 13 — Create New Stacked Branch
Tower 13 — Create New Stacked Branch


In the next dialog, you can select its parent branch for easy integration and choose to pin it and/or check it out immediately.

Tower 13 — Create New Stacked Branch Dialog
Tower 13 — Create New Stacked Branch Dialog

Managing Branches

You can also create a new stacked branch by right-clicking on any branch and selecting the preferred option from the context menu.

Additionally, you can perform all other common Graphite operations, such as renaming, merging, squashing, or deleting branches.

Tower 13 – Graphite Commands in Context Menu
Tower 13 – Graphite Commands in Context Menu

Setting the Parent Branch

At any moment, you can change the parent branch of a branch; this works in the same way as you would for Stacked Branches — by accessing the context menu and clicking on "Track Parent Branch."

In Graphite terminology, you may know this as "tracking" (gt track) and "untracking" (gt untrack) a stacked branch.

Tower 13 – Setting the Parent Branch
Tower 13 – Setting the Parent Branch

Restacking

Restacking synchronizes all changes by rebasing each child branch onto its parent branch. Tower will display an icon in the sidebar for the branches that require restacking, and you can easily perform this action by right-clicking the desired branch and selecting "Restack [Branch]".

In the branch's history view, you will also notice a yellow banner informing you that the branch needs restacking.

Tower 13 — Restack Branch
Tower 13 — Restack Branch


In the "Restack Branch" dialog, you will notice a "Restack Full Stack" option. If this option is not active, Tower/Graphite will restack the selected branch and all its parent branches. If the option is selected, the children of the branch will also be restacked (hence the name "full stack").

Tower will notify you of any conflicts that may arise during the restacking operation.

Tower 13 — Restack Branch Dialog
Tower 13 — Restack Branch Dialog

Syncing a Branch

Right-clicking any branch will also give you the option to "sync" it. As the name suggests, this will synchronize all the branches in the stack, similar to running the gt get command.

Tower 13 — Sync Branch Dialog
Tower 13 — Sync Branch Dialog


Tower also provides you with additional options, such as the ability to restack all branches in your repository.

Submitting a Branch (To Create a Pull Request)

You can submit a branch (effectively creating a PR) by right-clicking the branch and choosing the appropriate option from the context menu.

You can access additional options by clicking the drop-down arrow, such as updating only the branches that already have open PRs.

Tower 13 — Submit Branch to Graphite
Tower 13 — Submit Branch to Graphite


All available Pull Requests can be quickly accessed in Tower's "Pull Requests" view, located in the sidebar or by using the shortcut ⌘ + 4.

Tower 13 — Pull Requests
Tower 13 — Pull Requests


This view enables you to inspect, merge, close, comment on, or check out pull requests without the need to open a browser window.

Merge Queue

Graphite offers a Merge Queue feature that prevents semantic merge conflicts by automating the rebase process during merges. This ensures that the trunk branch remains "green", allowing development teams to progress more quickly with fewer disruptions.

In Tower, if merging is possible, the Graphite branch is added to the merge queue. The merge is performed asynchronously, so be sure to manually refresh and sync the branch afterwards to check if it has been merged.

When a Graphite branch is submitted to the merge queue, it is validated remotely to determine if it can be merged. If merging is possible, it is merged; if not, the process fails.

To run this operation, simply right-click the branch and select "Add [BRANCH] to Merge Queue…" from Tower's context menu.

Tower 13 — Graphite's Merge Queue
Tower 13 — Graphite's Merge Queue

Warning Messages

While using Tower, you may inadvertently disrupt Graphite's state by performing certain Git operations, such as a git push, shown below.

Tower will alert you whenever this situation may arise before you continue.

Tower 13 — Warning Message
Tower 13 — Warning Message


These prompts can be enabled and disabled by visiting the "Integration" tab in Tower's Settings.

Tower 13 — Integration Settings
Tower 13 — Integration Settings

Other Improvements

As usual, we have also taken the time to make some other enhancements behind the scenes.

Here is the list of improvements and bugs that we have worked on:

  • Rounded Avatars: Tower now displays rounded avatars for authors and committers.
  • Working Copy: Tower could crash if a user profile referenced an invalid signing key. This has been fixed.
  • History View improvements: Enhanced commit loading performance with signature verification enabled. Fixed issues with scroll position reset and empty list display . Resolved high CPU usage problem caused by GPG key server interactions.

We hope you enjoy this release! Happy stacking! 😊

Not a Tower user yet? Download our 30-day free trial and experience a better way to work with Git!




PS: Did you know? Tower Pro is now free for students as well as teachers and educational institutions!

]]>
Meet Graphite – The AI Developer Productivity Platform https://www.git-tower.com/blog/graphite https://www.git-tower.com/blog/graphite Wed, 30 Apr 2025 00:00:00 +0000 As developers, we love building things. What we don't enjoy as much is waiting: waiting for code reviews, getting blocked on merges, and the general friction that can sometimes slow down the development process.

If this resonates with you, then you'll want to hear about Graphite, a platform designed to tackle these very challenges head-on.

Graphite positions itself as an AI developer productivity platform, aiming to help engineering teams create, review, and merge smaller code changes more efficiently, stay unblocked, and ultimately ship faster.

In this post, let's find out how Graphite can help you accomplish just that.

Giving Time Back to Your Engineering Team

The folks at Graphite understand a core pain point for many engineering teams: code review can be a significant time sink. In fact, they point out that many engineers spend a day or more each week either reviewing code or stuck waiting for their own reviews to come through. That's a substantial chunk of valuable engineering time!

But Graphite believes it doesn't have to be this way. The team behind Graphite has a strong background, with many founding members hailing from tech giants like Meta and Google. These companies have, in many cases, developed their own internal code review tools to optimize their engineers' workflows. The Graphite team missed the power of these internal systems, particularly the stacked diffs workflow, which they initially leveraged in an internal tool.

The internal tool proved so effective that the team decided to pivot and focus entirely on developing it into the platform we now know as Graphite. Their mission is to bring the power of stacked pull requests – the very workflow that underpins best-in-class internal code review tools like Phabricator and Critique – to every software company.

Diamond – Embracing AI

Beyond just stacked PRs, Graphite also recognized the potential of AI early on, culminating in the release of Diamond (formerly known as Graphite Reviewer).

As a codebase-aware AI code review companion, it provides developers with immediate, actionable feedback on their pull requests, significantly reducing the number of review cycles. While other AI bots hallucinate and create noisy comments, Diamond is calibrated to catch real bugs and deliver smarter, targeted feedback with fewer false positives.

Diamond – Agentic AI Code Review
Diamond – Agentic AI Code Review


Diamond allows you to:

  • Merge PRs faster: Diamond automatically catches bugs and errors before human reviewers, letting your team spend less time on code review, and more time on building.
  • Enforce quality & consistency: Customize Diamond with repo-specific AI prompts and regex rules to enforce best practices across your entire team.
  • Keep your code private & secure: Diamond doesn't store or train on your team's code - your data remains yours.

The Results

The impact of Graphite speaks for itself. Tens of thousands of engineers at leading companies like Asana, Ramp, Tecton, and Vercel rely on Graphite daily to improve their development workflows.

Across these companies and many others, the average engineer using Graphite has seen some impressive results:

  • 1.3x's the number of PRs in flight: Engineers can manage and work on more changes concurrently.
  • Saves ~10 hours a week waiting to merge PRs: Less time spent blocked means more time spent building.
  • Merges 26% more PRs: A more efficient review process leads to a higher throughput of merged code.
  • Ships 20% more code (despite decreasing median per-PR size by 8%): Smaller, more frequent merges contribute to a higher overall shipping velocity.

These statistics highlight the tangible benefits that Graphite brings to engineering teams, translating directly into increased productivity and faster delivery cycles.

A Comprehensive Toolkit

Graphite isn't just about stacked PRs and AI; it's a comprehensive platform packed with features designed to streamline the entire software development lifecycle.

The platform includes:

  • CLI tool: For seamless integration with your existing Git workflow and powerful control over stacked PRs.
  • AI Code Review Companion: Providing intelligent, automated feedback directly on your pull requests.
  • VS Code Extension: Bringing the power of Graphite directly into your code editor.
  • Pull Request Inbox: A centralized hub for managing and prioritizing code reviews.
  • Code Review Tool: Offering a focused and efficient interface for reviewing code changes.
  • Workflow Automation Engine: Allowing teams to customize and automate their code review and merge processes.
  • Merge Queue: Ensuring smooth and automated merging of pull requests once they're approved.
  • Developer Productivity Insights: Providing valuable data and analytics to help teams understand and improve their development process.
Graphite – Developer Insights
Graphite – Developer Insights


All these components are thoughtfully designed to make the software development process as streamlined and effortless as possible.

How to Get Started with Graphite

Ready to experience the benefits of Graphite for yourself? The platform offers a free tier for small teams, making it easy to get started. Simply create your account by signing up with your email or GitHub account.

Give Graphite a try and see how it can help your team unlock new levels of productivity and efficiency in your development workflow!

]]>
Celebrating 20 Years of Git: 20 Interesting Facts From its Creator https://www.git-tower.com/blog/git-turns-20 https://www.git-tower.com/blog/git-turns-20 Thu, 17 Apr 2025 00:00:00 +0000 On April 7, 2005, a seemingly simple tool emerged that would fundamentally reshape the landscape of software development. Git, created by Linus Torvalds, was initially designed to solve a very specific problem: managing Linux kernel development after the departure of BitKeeper.

While many in the tech world might be aware of the remarkable speed at which Git's core functionalities were conceived – famously within a mere 10 days – the full story behind its creation and evolution is rich with surprising details and fascinating insights.

To celebrate this milestone, Linus was recently featured on GitHub's official YouTube channel (you can watch the video below or read the full interview with Taylor Blau). We thought this would be a great opportunity to present this conversation to the Tower community.

In this insightful conversation, Torvalds reflects on:

  • the origins of his groundbreaking project
  • his initial expectations (or lack thereof)
  • the key decisions that shaped Git into the ubiquitous version control system we know today.


Join us as we celebrate two decades of Git by exploring these engaging tidbits straight from the mind of its legendary creator!

Here are 20 interesting (and fun) facts about the early days of Git.

The original transcript has been lightly edited for the purpose of this blog post.

20 Facts About Git

1. Git was born out of necessity to solve a specific problem.

Linus Torvalds didn't embark on creating Git with the goal of global domination in mind. His primary motivation was to solve his own immediate problem: the need for a better version control system for the Linux kernel development. He had a strong negative opinion of existing systems like CVS and even felt his initial, raw version of Git was already an improvement.

"I saw it as a solution to my problems, and I obviously thought it was superior. Even literally 20 years ago to the day, I thought that first version, which was pretty raw — to be honest, even that version was superior to CVS."

2. The initial version of Git was developed in approximately 10 days.

While the groundwork and conceptualization took longer, the intensive coding period to get a working version of Git for kernel use was remarkably short, highlighting Linus's deep understanding of the requirements.

"It was actually fewer than — well, it was about 10 days until I could use it for the kernel, yes. But to be fair, the whole process started like December or November the year before, so 2004."

3. The reverse engineering of BitKeeper ultimately led to Linus creating Git.

The commercial nature of BitKeeper and the restrictions it placed on reverse engineering caused friction within the open-source kernel community. When this led to the loss of free BitKeeper usage, Linus felt compelled to create an open-source alternative.

"What did come up was that Tridge in Australia basically reverse engineered BitKeeper, which wasn’t that hard because BitKeeper internally was basically a good wrapper around SCCS, which goes back to the 60s. SCCS is almost worse than CVS. But that was explicitly against the license rules for BitKeeper. BitKeeper was like, you can use this for open source, but you can’t reverse engineer it. And you can’t try to clone BitKeeper. And that made for huge issues."

4. Linus spent about four months mentally planning the design of Git before writing the initial code.

The ten-day coding sprint was preceded by a significant period of thinking through the problems he wanted to solve and how Git could improve upon existing systems without infringing on BitKeeper's licensing.

"So by the time I started writing Git, I had actually been thinking about the issue for four months and thinking about what worked for me and thinking about “How do I do something that does even better than BitKeeper does but doesn’t do it the way BitKeeper does it?” I did not want to be in the situation where Larry would say, “Hey, you did the one thing you were not supposed to do.” So yes, the writing part was maybe 10 days until I started using Git for the kernel, but there was a lot of mental going over what the ideas should be."

5. For Linus, programming Git in userspace felt easier than dealing with the complexities of kernel development.

Working on a userspace tool allowed Linus to focus on higher-level logic without the low-level memory management and hardware considerations inherent in kernel development.

"And it was kind of interesting because it was — one of my reactions was how much easier it is to do programming in the userspace. There’s so much less you need to care about. You don’t need to worry about memory allocations. You don’t need to worry about a lot of things. And debugging is so much easier when you have all this infrastructure that you’re writing when you’re doing a kernel. So it was actually somewhat — I mean, I wouldn’t say relaxing, but it was fun to do something userspace-y where I had a fairly clear goal of what I wanted. I mean, a clear goal in the sense I knew the direction. I didn’t know the details."

6. A primary design goal for Git was performance, particularly in efficiently applying large series of patches.

Linus wanted Git to handle the numerous patches involved in kernel development quickly, aiming for operations that wouldn't even require a coffee break.

"But for me, one of the goals was that I could apply a patch series in basically half a minute, even when it was like 50, 100 patches. It’s one of those things where if things are just instant, some mistake happens, you see the result immediately and you just go on and you fix it. And some of the other projects I had been looking at took like half a minute per patch, which was not acceptable to me. And that was because the kernel is a very large project and a lot of these SCMs were not designed to be scalable."

7. The use of SHA-1 hashes in Git was primarily for detecting data corruption and ensuring stability, rather than for security purposes.

While SHA-1 provides a level of cryptographic security, Linus's main concern was data integrity, learning from issues encountered with BitKeeper's approach to data protection.

"And people kind of think that using the SHA-1 hashes was a huge mistake. But to me, SHA-1 hashes were never about the security. It was about finding corruption. Because we’d actually had some of that during the BitKeeper things, where BitKeeper used CRCs and MD5s, right, but didn’t use it for everything. So one of the early designs for me was absolutely everything was protected by a really good hash."

8. Git's low-level design is intentionally simple.

Linus drew a parallel to Unix's design philosophy, where a few fundamental ideas underpin a powerful and versatile system.

"Unix has like a core philosophy of everything is a process, everything is a file, you pipe things between things. And then the reality is it’s not actually simple. I mean, there’s the simple concepts that underlie the philosophy, but then all the details are very complicated. I think that’s what made me appreciate Unix in the first place. And I think Git has some of the same kind of, there’s a fundamental core simplicity to the design and then there’s the complexity of implementation."

9. Linus believes that the effort to support SHA-256 in addition to SHA-1 was largely a waste of time and resources, driven by unnecessary worry.

While understanding the concerns, he felt there wasn't a genuine need for the dual-hashing approach and that it led to "pointless churn."

"Well, I mean, SHA-1 I regret in the sense that I think it caused a lot of pointless churn with the whole “trying to support SHA-256 as well as SHA-1.” And I understand why it happened, but I do think it was mostly pointless. I don’t think there was a huge, real need for it, but people were worried, so it was short. So I think there’s a lot of wasted effort there."

10. During the initial development, Linus had a clear vision for the immediate steps but wasn't entirely certain about how all the pieces would ultimately fit together.

While he quickly achieved the ability to apply patches, other core functionalities like merging took more time and he wasn't always sure he would reach his goals.

"I had a clear idea of the initial stages but I wasn’t sure how it would work in the long run. So honestly, after the first week, I had something that was good for applying patches, but not so much for everything else. I had the basics for doing merges, and the data structures were in place for that, but it actually took, I think it took an additional week before I did my first merge. There were a number of things where I had kind of the big picture and result in mind, but I wasn’t sure if I’d get there."

11. The very first versions of Git were rudimentary because there was a more important project to prioritize.

The initial focus was on getting the core functionality working for kernel development, with robustness and more advanced features added over time.

"Yeah, the first steps, I mean the first week or two, I mean, you can go and look at the code — and people have — and it is not complicated code. I think the first version was 10,000 lines or something. You can more or less read it in a single sitting. Yeah, and it’s fairly straightforward and doesn’t do a lot of error checking and stuff like that. It’s really a, “Let’s get this working because I have another project that I consider to be more important that I need to get back to.” It really was."

12. Early Git usage involved direct manipulation of low-level "plumbing commands" and manual editing of files.

Basic operations like committing required arcane sequences of commands that directly interacted with Git's underlying object store.

"I mean, the first week when I was using it for the kernel, I was literally using the raw, what are now called “plumbing commands” by hand. Of course. Because there was no so-called porcelain. There was nothing above that to make it usable. So to make a commit, you’d do these very arcane things. Set your index, commit-tree. Yeah, commit-tree, write, and that just returns an SHA that you write by hand into the head file and that was it."

13. The hash-object command, fundamental for Git's content-addressable storage, was one of the earliest binary utilities Linus created.

This allowed him to verify the core hashing mechanism by manually hashing data and checking the output.

"I think that was one of the first binaries that I had where I could just check that I could hash everything by hand and it would return the hash to standard out, then you could do whatever you wanted to it."

14. The initial user interface "porcelain" for Git consisted of shell scripts written by Linus to wrap the difficult-to-use plumbing commands.

Making Git accessible required building higher-level tools on top of the core commands. Linus's initial attempts were in the form of simple scripts, which weren't particularly user-friendly.

"But it was like the early porcelain was me scripting shell scripts around these very hard-to-use things. And honestly, it wasn’t easy to use even with my shell scripts."

15. The first target audience for Git was the hardcore kernel developers who were already familiar with some of the concepts from using BitKeeper.

Their prior experience with a more advanced VCS made them more receptive to Git's underlying ideas.

"But to be fair, the first initial target audience for this were pretty hardcore kernel people who had been using BitKeeper. They at least knew a lot of the concepts I was aiming for. People picked it up."

16. Linus handed over the maintainership of Git to Junio Hamano relatively early in the project.

After only three or four months of his own stewardship, Linus recognized the need to focus on the kernel and trusted Junio's capabilities to lead Git's further development.

"I mean, to be honest, I maintained Git for like three or four months. I think I handed it off in August [of 2005] or something like that. And when I handed it off, I truly just handed it off. I was like, “I’m still around.” I was still reading the Git mailing list, which I don’t do anymore. Junio wanted to make sure that if he asked me anything, I’d be okay. But at the same time, I was like, this is not what I want to do."

17. Linus's criteria for choosing Junio as the maintainer was largely based on his "taste" in code.

He valued Junio's judgment and his understanding of the project's direction.

"But to be honest I’ll take credit for having worked with people on the internet for long enough that I was like — during the four months I was maintaining Git, I was pretty good at picking up who has got the good taste to be a good maintainer. That’s what it’s about — taste — for you. For me, it’s hard to describe. You can see it in patches, you can see it in how they react to other people’s code, “how they think” kind of things."

18. Git's distributed nature, where every repository is a full copy with complete history, was a key design principle.

This architecture made local work and later sharing incredibly easy. It also differentiated it from most previous centralized version control systems and contributed to its widespread adoption.

"So the distributed nature really ends up making so many things so easy and that was one big part that set Git apart from pretty much all SCMs before, was… I mean there had been distributed SCMs, but there had, as far as I know, never been something where it was like the number one design goal — I mean, along with the other number one design goals — where it means that you can work with Git purely locally and then later if you want to make it available in any other place it’s so easy. And that’s very different from, say, CVS where you have to set up this kind of repository and if you ever want to move it anywhere else it’s just very very painful and you can’t share it with somebody else without losing track of it."

19. Linus believes that Git's fundamental design, emphasizing easy copying and the equality of all repositories, made services like GitHub "trivial" at their core.

The underlying architecture of Git facilitated the creation of centralized hosting platforms.

"And the fact that Git didn’t do that, and very much by design didn’t do that, I mean that’s what made services like GitHub trivial. I mean I’m trivializing GitHub because I realized there’s a lot of work in making all the infrastructure around Git, but at the same time the basic Git hosting site is basically nothing because the whole design of Git is designed around making it easy to copy, and every repository is the same and equal."

20. Linus was amused by the initial wave of complaints about Git's user interface, particularly the naming of commands, as he sometimes deliberately chose different names than CVS simply because he disliked it.

The transition from older systems led to confusion and criticism, but Linus had his own reasons for some of the seemingly arbitrary choices.

"Oh, the complaints kept coming. Tell me about it. Oh, I mean, it’s more like I can’t point to details. You’d have to Google it. But the number of people who sent me, “Why does it do this?” And the flame wars over my choice of names. For example, I didn’t have git status, which actually is one of the commands I use fairly regularly now... So I just remember the first few years, the complaints about why the names of the subcommands are different for no good reason. And the main reason was I just didn’t like CVS very much, so I did things differently on purpose sometimes."

Final Words

So there you have it: 20 interesting facts about the early days of Git!

Here at Tower, as passionate fans and dedicated users of Git ourselves, we join the global community in celebrating this remarkable 20-year milestone. We recognize and appreciate the profound influence Git has had on our daily work and the collaborative spirit of software development as a whole.

Here's to many more years of Git! 🥂

We hope you found this post helpful. For more Git tips and tricks, don't forget to sign up for our newsletter below and follow Tower on Twitter / X and LinkedIn! ✌️

]]>
How to Exclude Commits from Git Blame https://www.git-tower.com/blog/how-to-exclude-commits-from-git-blame https://www.git-tower.com/blog/how-to-exclude-commits-from-git-blame Wed, 16 Apr 2025 00:00:00 +0000 Ah, git blame! The detective of Git-land, diligently pointing its finger at the author of each line of code. But sometimes, the blame game can get a little… noisy.

What if you're trying to understand the evolution of a critical piece of logic, but all you see are commits related to code formatting or a massive refactoring that touched almost every file? These commits, while important in their own right, can sometimes obscure the more granular history you're trying to uncover.

Thankfully, there are ways to tell git blame to politely ignore certain commits, allowing you to focus on the changes that truly matter. This is what this article is all about.

Today, we will explore the situations in which it makes sense to exclude commits and examine our options.

But first, here's a brief overview of the purpose of git blame.

About the "Git Blame" Command

At its core, git blame is a Git command that displays the author and revision information for each line of a file.

The primary purpose of this command is to understand the history of a specific piece of code. It helps you answer questions like:

  • Who wrote this line of code?
  • When was this line last changed?
  • Why was this change made (by examining the commit message)?

It works by traversing the commit history of a file; starting from the current version of the file, it looks back through the commits that have modified it, line by line. For each line, it identifies the commit that introduced or last changed that particular line.

Git cleverly tracks line movements across commits. So, if a line of code is moved to a different location within the same file or even to another file (in some cases), git blame can often still trace its original author and commit.

This makes it a powerful tool for understanding the evolution of your codebase — way more reliable than your colleague John!

John versus Git Blame!
John versus Git Blame!


Jokes aside, for every line in the specified file, git blame shows:

  • The commit hash of the last commit that modified that line.
  • The author of that commit.
  • The date and time of that commit.
  • The actual line of code.

This information is essential for debugging, understanding legacy code, and collaborating effectively within a team.

Why Exclude Commits From Git Blame?

While git blame is incredibly useful, there are scenarios where certain types of commits can clutter the output and make it harder to find the information you're really looking for.

Imagine the following situations:

  • Massive Code Formatting: Your team decides to adopt a stricter code style and runs an automated formatter across the entire codebase. This results in a commit that touches almost every line of every file, but doesn't change any functional logic.
    Running git blame after this commit might show the formatter as the author of large sections of the code, obscuring the original authors and the actual evolution of the logic.
  • Large-Scale Refactoring: A significant refactoring effort might involve moving code around, renaming variables, or restructuring directories without fundamentally changing the behavior of the code. These commits can also dominate the git blame history, making it difficult to see the more fine-grained changes.
  • Automated Script Changes: Commits generated by automated scripts, such as dependency updates or generated code, might not provide much useful context when you're trying to understand the human-written parts of the code.
  • Cherry-Picks and Merges: Sometimes, cherry-picking or merging commits can result in changes that don't accurately reflect the original authorship in the target branch's history. Excluding the merge commit itself might provide a cleaner view of the individual contributions.

This is where the ability to exclude commits comes in handy. So let's have a look at how it works in practice.

How to Exclude Commits from Git Blame

Git provides a couple of powerful ways to exclude specific commits from the git blame output:

  • Option 1: Creating a .git-blame-ignore-revs File
  • Option 2: Command-Line Options for git blame

Let's explore both methods.

Option 1: Creating a .git-blame-ignore-revs File

The .git-blame-ignore-revs file is a configuration file that allows you to specify a list of commit hashes (or SHAs — Secure Hash Algorithm) that git blame should ignore.

💡 Please note that .git-blame-ignore-revs is merely a convention; Git does not automatically use this file in the same manner as it does with the .gitignore file.

However, we recommend using this file name, as popular code hosting platforms like GitHub and GitLab look for and support this file.

1. Creating and Using the File

To use this feature, you first need to create a file named .git-blame-ignore-revs at the root of your Git repository. This file should contain a list of commit hashes/SHAs, with one hash per line.

For example, your .git-blame-ignore-revs file might look like this:

# Removed semi-colons from the entire codebase
a1b2c3d4e5f678901234567890abcdef01234567
# Converted all JavaScript to TypeScript
fedcba9876543210fedcba9876543210fedcba98

Each line in this file represents a commit that you want git blame to skip over when tracing the history of a file. Comments are optional but recommended.

2. Syntax for Listing Commits to Ignore

The syntax for the .git-blame-ignore-revs file is straightforward: simply list one full commit hash per line. You can obtain these hashes using commands like git log or by inspecting your Git history in Tower.

Finding the Commit Hash in Tower
Finding the Commit Hash in Tower


It is important to use the full SHA-1 hash to ensure Git correctly identifies the commits to ignore.

3. Configuring Git to Use the File

Once you've created and populated the .git-blame-ignore-revs file, you need to tell Git to actually use it. You can do this by setting the blame.ignoreRevsFile configuration option.

To enable this for your current repository, run the following command in your terminal:

git config blame.ignoreRevsFile .git-blame-ignore-revs

To enable it globally for all your Git repositories, use the --global flag:

git config --global blame.ignoreRevsFile .git-blame-ignore-revs

With this configuration in place, whenever you run git blame on a file in your repository (or any repository if you used the --global option), Git will automatically skip over the commits listed in your .git-blame-ignore-revs file.

If a line's last modification was in an ignored commit, git blame will continue to trace the history back to the commit before the ignored one.

Option 2: Command-Line Options for git blame

For more ad-hoc or one-off exclusions, git blame also provides command-line options to ignore specific commits or an ignore file.

1. The --ignore-rev Option

The --ignore-rev option allows you to specify one or more commit hashes/SHAs directly in your git blame command.

To ignore a single commit, you would use:

git blame --ignore-rev <commit-sha> <file>

To ignore multiple commits, you can use the option multiple times:

git blame --ignore-rev <commit-sha-1> --ignore-rev <commit-sha-2> <file>

This option is useful when you quickly want to exclude a specific commit without modifying the .git-blame-ignore-revs file.

2. The --ignore-revs-file Option

If you have a file containing the list of commits to ignore (which doesn't necessarily have to be named .git-blame-ignore-revs or located at the repository root), you can explicitly tell git blame to use it with the --ignore-revs-file option:

git blame --ignore-revs-file <path/to/ignore-file> <file>

This can be helpful if you want to maintain different ignore lists for different purposes or if you prefer to keep the ignore list in a non-standard location.

Best Practices for Excluding Commits

While the ability to exclude commits from git blame is powerful, it's important to use it judiciously and follow some best practices.

Here are 4 tips you should keep in mind.

1. Maintaining the Ignore List

If you choose to use the .git-blame-ignore-revs file, it's important to maintain it over time. As your project evolves, you might encounter new formatting or refactoring commits that you want to add to the ignore list.

Consider keeping the ignore list relatively concise and focused on truly disruptive commits. A very long ignore list might indicate a broader issue with your commit history or development practices.

2. Communicating Excluded Commits to the Team

If you are using the repository-specific .git-blame-ignore-revs file (i.e., you configured blame.ignoreRevsFile without the --global flag), it's a good idea to communicate to your team that this file exists and what types of commits are being ignored. This ensures that everyone on the team is aware of the potential differences in their git blame output.

Since .git-blame-ignore-revs is typically committed to the repository, it automatically shares the ignore list with everyone who clones the project. However, it's still helpful to mention its existence in your project's documentation or during team meetings.

3. Balancing Exclusion with Accountability

While excluding certain commits can improve the clarity of git blame output, it's important to maintain accountability. Don't use commit exclusion as a way to hide authorship of problematic code. The primary goal is to improve the signal-to-noise ratio, not to rewrite history or evade responsibility.

Remember that the excluded commits are still part of the Git history and can be examined using other Git commands like git log. git blame with exclusions simply provides a filtered view.

4. Integrating Exclusion into Your Workflow

Consider integrating the creation or updating of the .git-blame-ignore-revs file as part of your team's workflow when performing large-scale formatting or refactoring. For example, the script that performs the formatting could also generate or append to the ignore list.

Using a repository-specific .git-blame-ignore-revs file and enabling it via git config within the repository ensures that the ignore rules are automatically applied for everyone working on that project. This provides a consistent and cleaner git blame experience for the entire team.

Final Words

We've journeyed through the ins and outs of excluding commits from git blame, from understanding its purpose to mastering the techniques for filtering out noise.

Whether you choose to use the .git-blame-ignore-revs file for persistent exclusions or the command-line options for more targeted filtering, you now have the tools to make your code history investigations more focused and efficient. So go ahead and use these techniques wisely!

We hope you found this post helpful. For more Git tips and tricks, don't forget to sign up for our newsletter below and follow Tower on Twitter / X and LinkedIn! ✌️

]]>
Tower 9.0 for Windows — Git Worktree Support https://www.git-tower.com/blog/tower-windows-9 https://www.git-tower.com/blog/tower-windows-9 Mon, 31 Mar 2025 00:00:00 +0000 For those of you eagerly awaiting Git Worktree support in Tower, your patience has paid off! We're thrilled to announce that Tower 9.0 for Windows brings this powerful feature directly to your favorite Git client.

After bringing Git Worktree support to Tower for Mac earlier this year, it's now Windows' turn! With this release, you can easily create, check out, and manage Worktrees right from within Tower!

Let's first explore what makes git-worktree so useful and then see how easy it is to perform all Worktree operations in Tower.

The Power of "Git Worktree"

In short, git-worktree allows you to simultaneously work on different branches without the usual conflicts and disruptions. This is a game-changer when you need to switch gears for urgent tasks, like a hotfix, without interrupting your current work.

Traditionally, you might have resorted to:

  • Stashing your changes, which can be cumbersome and prone to forgotten details.
  • Creating incomplete commits, which require later edits and can clutter your history.

With worktrees, you can seamlessly transition between branches or pull requests, maintaining a clean and organized workflow 😎

Another significant advantage is handling long-running processes. You can execute time-consuming operations like builds or tests in one worktree while continuing development in another, ensuring uninterrupted productivity.

Worktrees differ from branches in their directory structure. Each worktree has its own distinct working directory — which is why it is recommended to create worktrees outside your main project folder, to avoid redundancy.

Furthermore, worktrees are resource-efficient. They share the underlying Git repository data (objects and refs), minimizing disk space usage compared to multiple clones and offering faster performance.

Worktrees in Tower for Windows

Tower provides an intuitive interface for managing and switching between worktrees.

With this new update, you will notice a dedicated "Worktrees" section conveniently located in the sidebar, following "Submodules".

Tower 9.0 – Worktrees in the sidebar
Tower 9.0 – Worktrees in the sidebar

Creating a New Worktree

There are several ways to create a new worktree in Tower. One method is to right-click on any branch and select "Check out [BRANCH] in New Worktree..." from the context menu.

Tower 9.0 – Creating a New Worktree from the Context Menu
Tower 9.0 – Creating a New Worktree from the Context Menu


Alternatively, you can use the "+" button at the bottom of the sidebar or navigate to "Repository" > "Add New Worktree…" in the main menu.

Tower 9.0 – Creating a New Worktree by clicking the
Tower 9.0 – Creating a New Worktree by clicking the "+" button


In the dialog box, specify the desired location for the worktree and the branch to use as a starting point.

Upon clicking "Create Worktree", a new worktree will be generated and automatically checked out, ready for use!

Tower 9.0 – Creating a New Worktree dialog
Tower 9.0 – Creating a New Worktree dialog


Fans of drag-and-drop actions will appreciate that you can easily drag a branch to the "worktree" section to instantly create a worktree based on that branch. By the way, this also works with commits, not just branches 😉

Creating a New Worktree with Drag and Drop

Managing Worktrees in Tower

Tower visually distinguishes worktrees with a unique icon within the "Branches" section, making them easily identifiable.

Tower 9.0 – Worktrees in the
Tower 9.0 – Worktrees in the "Branches" section


Right-clicking on a worktree provides options to remove it, relocate it, or open it in the terminal or Explorer, offering comprehensive control.

Tower 9.0 – Worktree options
Tower 9.0 – Worktree options


A New Compact Top Bar Layout

With this release, we've also introduced a new compact top bar layout for a cleaner appearance.

Tower 9.0 – Compact Top Bar Layout
Tower 9.0 – Compact Top Bar Layout


To try it out, enable "Use compact top bar layout" in "Preferences > General." Changes will be applied after restarting Tower.

Tower 9.0 – Enabling the Compact Top Bar Layout
Tower 9.0 – Enabling the Compact Top Bar Layout


Other Improvements

As always, we've also taken a moment to address some other small improvements and bug fixes, such as:

  • SSH Keys: Fixed retrieval from 1Password.
  • Rebase: Fixed commit message editing during rebase operations.
  • Services: Fixed issues with adding custom accounts and GitLab authentication issues.
  • Ignore & Exclude Files: Fixed an issue where these files did not open correctly. They now function as expected.
  • Cherry-Picking: Fixed the issue where commits were applied in the wrong order, ensuring they now follow the expected sequence.

For the complete changelog, please have a look at the Release Notes.

We hope you enjoy our latest Windows release. Happy committing! 😊

New to Tower? Download our 30-day free trial and discover a more efficient way to work with Git!




PS: Did you know? Tower Pro is now free for students as well as teachers and educational institutions!

]]>
The Honest Git Glossary https://www.git-tower.com/blog/honest-git-glossary https://www.git-tower.com/blog/honest-git-glossary Tue, 11 Feb 2025 00:00:00 +0000 The Honest Git Glossary is a fun (and honest!) way to learn the most popular Git commands.

Have a laugh and share it with your developer friends!


The Honest Git Glossary
The Honest Git Glossary


We hope you find this fun cheat sheet helpful…

…but if you're tired of Googling commands, we invite you to try Tower, our Git client, available for both Mac and Windows!

Tower app icon
]]>
Tower 12.5 for Mac — Hello Worktrees! 👋 https://www.git-tower.com/blog/tower-mac-125 https://www.git-tower.com/blog/tower-mac-125 Wed, 05 Feb 2025 00:00:00 +0000 Tower 12.5 for Mac is here, bringing one of our users' most requested features: Worktree support! Now you can create, check out, and manage Worktrees directly from within your favorite Git client! 🫡

If you are a fan of worktrees and have been hoping for Tower to support them, we have great news for you: the wait is over!

Let's take a look at this native Git feature and explore what you can do in Tower.

What is "Git Worktree" all about?

The git-worktree feature was introduced in version 2.5.0 of Git. The main advantage is that it allows you to have multiple working trees attached to the same repository, enabling you to check out more than one branch simultaneously from a single repository.

This is especially useful when someone asks you to work on a hotfix, for example, requiring you to leave your current work unfinished.

In such cases, with regular branches, you would either need to:

  • stash your changes to check out a different branch
  • create an unfinished commit, which you might need to edit later... if you remember to do so!

With worktrees, you can check out as many branches or pull requests as you'd like without worrying about having a clean working copy 😎

Another great use case is for long-running operations. You can perform time-consuming tasks, such as large builds or extensive tests, in one worktree while continuing to work in another. Worktrees are great for staying in the flow!

There are other differences to keep in mind when compared to branches. Unlike branches, which share the same working directory, each worktree has its own distinct working directory. It is best to create your worktrees outside of your project folder, as you wouldn't want a duplicate copy of your files inside your current worktree.

Your hard drive will also appreciate worktrees, as they are more lightweight. All worktrees share the same Git repository data (objects and refs), which saves disk space compared to having multiple clones and is generally faster than creating a new clone of the repository.

Now that you can see the benefits of this feature, let's see how you can work with Worktrees in Tower.

Working with Worktrees in Tower

Tower makes it easy to manage your worktrees and quickly check them out. You can find a new "Worktrees" section available in the sidebar, after "Submodules".

Tower 12.5 – Worktrees in the sidebar
Tower 12.5 – Worktrees in the sidebar

Creating a New Worktree

Creating a new worktree in Tower couldn't be easier: simply right-click any branch and select "Check out [BRANCH] in New Worktree..." from the context menu.

Tower 12.5 – Creating a New Worktree from the Context Menu
Tower 12.5 – Creating a New Worktree from the Context Menu


Alternatively, you can click the "+" button located at the bottom of the sidebar or select "Repository" > "Add new Worktree…" from the main menu.

Tower 12.5 – Creating a New Worktree by clicking the
Tower 12.5 – Creating a New Worktree by clicking the "+" button


In the dialog, you will be prompted to select the location where you would like the worktree to be saved, as well as the branch you would like to use as a starting point.

After clicking "Create Worktree", a new worktree will be created and automatically checked out!

Tower 12.5 – Creating a New Worktree dialog
Tower 12.5 – Creating a New Worktree dialog


Managing Worktrees in Tower

Worktrees have a distinct icon, making it easy to identify when a branch is checked out in a worktree.

Tower 12.5 – Worktrees in the
Tower 12.5 – Worktrees in the "Branches" section


By right-clicking on any worktree, you can remove it, move it to a new location, or explore it in the terminal or Finder by selecting the appropriate option from the context menu.

Tower 12.5 – Worktree options
Tower 12.5 – Worktree options


We hope you enjoy this release! Happy committing! 😊

Not a Tower user yet? Download our 30-day free trial and experience a better way to work with Git!




PS: Did you know? Tower Pro is now free for students as well as teachers and educational institutions!

]]>
Markdown's Big Brother: Say Hello to AsciiDoc https://www.git-tower.com/blog/asciidoc-quick-guide https://www.git-tower.com/blog/asciidoc-quick-guide Tue, 21 Jan 2025 00:00:00 +0000 We’ve all been there: a single README.md file was enough in the early days of your project. But as new features and contributors rolled in, maintaining that lightweight Markdown file started feeling like juggling knives.

Suddenly you needed tables, cross-references, conditional text, and more. Your once-lean documentation stack was becoming a tangle of extensions, custom scripts, and half-baked solutions. Enter AsciiDoc!

If you’ve been relying on Markdown and occasionally fighting its quirks, AsciiDoc might be the structured, fully-featured alternative you didn’t know you needed. In this guide, we’ll walk through AsciiDoc’s essentials and share tips on how to make your documentation easier to maintain, especially if you’re using version control tools like Git (and even better if you’re using Tower).

Markdown vs. AsciiDoc – An Overview

Markdown’s Strengths (and Limitations)

No one’s knocking Markdown. It’s famous for:

  • Simplicity: You can learn the basics in minutes (# Heading, - Lists, **Bold**).
  • Widespread Support: From GitHub to countless blogging platforms, Markdown is everywhere.
  • Readable Syntax: Markdown files look decent even in raw form.

However, Markdown can become cumbersome when your docs grow large or require advanced features. To handle tables, footnotes, or custom formatting, you often rely on third-party extensions. That’s where compatibility headaches can pop up.

AsciiDoc’s Superpowers

By contrast, AsciiDoc was built to tackle complex documentation without relying on scattered extensions. Out of the box, it handles:

  • Tables, footnotes, and cross-references with minimal fuss.
  • Document composition: Include or reference multiple AsciiDoc files to keep large projects organized.
  • Attributes and conditional content for flexible, multi-version outputs.

AsciiDoc has a unified ecosystem rather than a million “flavors” or "dialects". If you’ve ever battled Markdown dialects, you’ll appreciate the consistency.

To sum it up: AsciiDoc is Markdown on Steroids.

Writing in AsciiDoc - An Example

Let’s say you’re documenting the user guide for an application. Let's see how we can set it up in AsciiDoc:

Setting the Stage: Document Metadata

AsciiDoc doesn’t force you to create a separate config file for metadata. You can embed it directly in the document header:

= User Guide for adoc Studio
Author: Marvin Blome
Date: 2025-01-21

That’s it. You get a title, author, and date right in your source file. No extra YAML required.

Organizing with Headings

Next up, we want to outline our document's structure. For this, we use headings. In AsciiDoc, they are written with = signs. The number of equals signs corresponds to the heading level:

= User Guide for adoc Studio
== Basic Topics
=== Features
=== Installation
== Advanced Topics
=== ...

It’s readable and easy to spot your document’s structure at a glance, even if you’re looking at the raw text.

Text Formatting - Similar to Markdown

If you’ve used Markdown, you’ll feel right at home with AsciiDoc’s basic text styling:

*Bold Text*
_Italicized Text_
`Monospaced Text`

Rendered, these become bold, italic, and monospaced respectively.

Text Formatting in AsciiDoc
There are plenty of formatting options in AsciiDoc

Making Content Scannable via Lists

Let’s be honest, most readers skim for the key points. That’s where lists come in handy, and setting them up in AsciiDoc couldn’t be easier:

// Unordered List
* Item 1
* Item 2

// Ordered List
. Step 1
. Step 2
. Step 3

Ordered lists automatically re-number if you move items around – no awkward re-typing of numbering.

Tables Without Tears

When Markdown tables get complicated, you often fall back on hacky solutions or HTML. AsciiDoc tables, on the other hand, use a simple grid syntax:

|===
| Task | Status | Due Date
| Write draft | In Progress | Jan 20, 2025
| Review draft | Pending | Jan 22, 2025
|===

This is a breeze to maintain in version control because each table row is on its own line. That means clear diffs in Git, without the confusion of multi-line Markdown tables.

Quick Tip: Use the Apple Text Replacement to insert table templates. Create a shortcut like table() and watch it expand into a skeleton table.

Attributes: Reusable Variables

Ever wish you could define a variable once and reuse it everywhere? That’s what attributes are for in AsciiDoc.

Attributes in AsciiDoc
Attributes in AsciiDoc


Change :app-name: and other attributes in the definition, and they update across your document. Perfect for version numbers, website URLs and other recurring text.

Splitting Your Docs: Include Directive

Large teams (and large documentation projects) benefit from modular files. Instead of one giant .adoc file, you can keep each section separate and include them dynamically:

include::introduction.adoc[]
include::features.adoc[]

Imagine a scenario where your advanced tips only apply to the enterprise version of your software. Keep them in a separate file and include them only where you need them.

Conditional Content

Take modularity a step further by toggling content based on attributes. This is especially handy if you maintain both a beginner guide and an advanced guide:

ifdef::beginner[]
== Welcome, New Users!
endif::[]

ifdef::advanced[]
== Advanced Tips and Tricks
endif::[]

Activate those attributes in the text or directly in the export. With that, you can create multiple outputs from a single master document.

Exporting AsciiDoc Files

Once you’ve harnessed AsciiDoc’s advanced features, the next question is: How do you export all this work? Typically, you’d hop into a terminal and run commands like asciidoctor -b html5 myfile.adoc. Here you'd need to create and maintain long scripts for every format and export.

This is where adoc Studio comes into play.

adoc Studio’s Approach


adoc Studio is an AsciiDoc editor that bundles everything you need to write, organize, and export your docs in one place. Rather than juggling scripts or dealing with multiple tools for PDF, HTML, or other formats, you can define your:

  • Attributes (like beginner or advanced)
  • Formats (HTML, PDF, etc.)
  • Stylesheets (for consistent branding across documents)

…and store them as “products” in the app. This keeps your writing flow uninterrupted and your design consistent.

Attributes Product Example
Attributes Product Example


If you need a quick refresher on syntax while writing, the built-in adoc Coach pops up with suggestions. Just hit ESC and explore what’s possible in your current context.


While AsciiDoc itself is platform-agnostic, editors like adoc Studio can make the experience more efficient:

  • Unified Styles: While AsciiDoc requires individual stylesheets for all formats, adoc Studio only requires one CSS for both HTML & PDF.
  • No Terminal Required: If the command line isn’t your friend, the app provides a user-friendly GUI for exports.
  • Mobile-Friendly: adoc Studio is available for Mac, iPad, and iPhone, making quick edits on the go surprisingly easy.
adoc Studio Devices
adoc Studio Devices


If you’re curious, there’s a 14-day free trial. Afterward, you can subscribe monthly or annually.

Docs-as-Code with Git

For many developer teams, documentation is an integral part of the software itself. That’s where Docs-as-Code comes in. By storing your AsciiDoc files in a Git repository, you can:

  1. Collaborate effortlessly – Each pull request shows exactly what changed in your docs, just like you’re used to with code.
  2. Branch and merge safely – Work on future documentation in a separate branch without disturbing your main docs.
  3. Track history – Roll back if something goes wrong or reference how docs have evolved over time.

AsciiDoc plays nicely with Git because it’s plain text. Each line is easily diffed, so you can see changes without wading through messy binary differences. And if you’re using Tower, you get a slick interface to manage your repositories, branches, and merges.

Parting Thoughts

AsciiDoc might look like just another markup language, but under its lightweight syntax lies a powerful engine for creating and maintaining professional documents. Whether you’re producing user guides, release notes, or full-blown technical manuals, AsciiDoc gives you the structure, flexibility, and control that can be elusive in simpler formats.

If you want to learn more about the markup language, check out the Complete Guide to AsciiDoc on adoc Studio's blog.

Happy documenting!

]]>