Beyond “Commit” and “Push”: 5 Advanced Git Features You Should Know
July 2024 by Bruno Brito

Beyond “Commit” and “Push”: 5 Advanced Git Features You Should Know

Many developers work with Git every day, adding commits, creating branches, and pushing or pulling the latest changes. However, Git offers a wide range of advanced features beyond these basics that few developers know about.

Let's change that!

Today, we will explore five of Git's hidden gems. These advanced features, often overlooked by even seasoned developers, showcase the depth and flexibility of Git.

We will cover:

  1. Git Bisect
  2. Git Rerere
  3. Git Attributes
  4. Git Notes
  5. Git Worktree

Whether you're a solo developer or part of a large team, understanding and leveraging these features can take your version control game to the next level.

Hop on board the Git train! 🚂

1. Git Bisect

Git Bisect is a powerful debugging tool that helps you pinpoint the exact commit that introduced a bug in your project. This feature is a great example of how Git can be much more than just a version control system, offering valuable debugging capabilities as well!

Imagine you discover a bug in your current version, but you know it was working fine 3 months ago. Instead of manually checking every commit from the last 3 months, you can use Git Bisect to quickly narrow down to the exact commit that introduced the issue, potentially saving hours of debugging time.

This command uses a binary search algorithm to efficiently narrow down the problematic commit, which can be incredibly useful when dealing with large codebases or long periods between discovering a bug and its introduction.

Here's how it works:

  • First, you need to inform Git of a commit where the code is working correctly (the "good" commit) and another commit where the bug is present (the "bad" commit).
  • Git then selects a commit that lies halfway between the two points you provided and prompts you to confirm whether the bug is present in that commit.
  • This iterative process continues as Git narrows down the range of commits until it pinpoints the exact commit that introduced the bug.

Here's how you can get started with Git Bisect:

$ git bisect start
$ git bisect bad  # Current version is "bad"
$ git bisect good <good-commit-hash> # Commit that is known to be "good"
# Git then checks out a commit for you to test and you mark it as "good" or "bad"
$ git bisect good  # or git bisect bad, depending on your conclusion
# Repeat until Git identifies the problematic commit
$ git bisect reset  # to end the bisect session

Git Bisect offers a visualization option that can be quite handy. You can use git bisect visualize to display a graphical representation of the commit history being analyzed.

You could also write a script to automatically test each commit, for even faster debugging. You would then execute it by typing git bisect run ./script.sh.

Git Bisect offers a wide range of powerful subcommands. You can explore the complete list of features here.

2. Git Rerere

The name "Rerere" might make you chuckle, but if you find yourself dealing with the same Git conflicts often, you will love this feature!

Rerere stands for "Reuse Recorded Resolution"; as the name suggests, it allows Git to remember how you've resolved a merge conflict so that it can automatically resolve it the same way if it encounters the same conflict again.

This is particularly useful when working with long-lived topic branches, as you may encounter the same conflicts repeatedly.

To enable rerere, you'll just need to type the following:

$ git config --global rerere.enabled true

Once enabled, Git will automatically record how you resolve conflicts and reuse these resolutions in future conflicts.

This command is usually run without arguments or user intervention, but you can learn more about Git Rerere here.

We make Tower, the best Git client.

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


3. Git Attributes

Git Attributes enable you to define attributes for paths within your repository. These attributes can control Git's behavior for specific files or directories. They're especially useful in projects with mixed file types, cross-platform development, or when certain files require specific handling.

They allow you to customize Git's behavior on a per-repository or even per-file basis. These attributes are defined in a .gitattributes file that you can add to the root of your repository.

This feature can be quite useful in a couple of scenarios. Firstly, it allows you to specify to Git which files should be treated as binary data. For example, certain text files (such as those ending in .pbxproj from Xcode projects) should be treated this way because their changes cannot be merged, and viewing the differences is not really helpful.

To instruct Git to recognize all .pbxproj files as binary data, you can include the following line in your .gitattributes file:

*.pbxproj binary

You can also use this feature to compare binary files, such as Microsoft Word documents! You can use the diff key attribute like in the following example:

*.docx diff=word

This command instructs Git to apply the "word" filter to any file matching the .docx pattern when reviewing a diff with changes. The "word" filter needs to be set up by downloading and installing a program like docx2txt, that can convert Word documents to text files for accurate diff comparison.

Finally, you can also use the merge key attribute to use different merge strategies for specific files in your project. This is quite helpful when you want to merge a branch ignoring certain files, such as a database file.

You can add the following line to the .gitattributes file:

*.db merge=ours

And then define a dummy ours merge strategy with:

$ git config --global merge.ours.driver true

In this scenario, database.db will remain at its original version.

A lot more could be written about .gitattributes, so we encourage you to check its documentation here.

4. Git Notes

Git Notes enable you to add or inspect notes on objects. Think of these notes as comments that you can associate with objects (usually commits) without changing the object itself.

These notes can be helpful for code reviews, providing context to automated processes, or as reminders for yourself or your team.

To add a note to the current commit, type the command below:

$ git notes add -m "This is a note"

The command above will work for the current commit, but you can also add a commit hash to reference a specific one.

To edit or remove a note, you can use:

$ git notes edit <commit-hash>
$ git notes remove <commit-hash>

You can view a commit's notes by typing:

$ git notes show <commit-hash>

You can learn more about this command here.

5. Git Worktree

Git Worktree is a useful feature for developers who frequently switch contexts between different parts of a project or need to perform parallel operations on different branches.

It allows you to work on multiple branches simultaneously without stashing or committing partial work. Git Worktree also makes it easy for you to build or test different versions of your project concurrently and perform long-running operations on one branch while working on another.

Let's imagine you are working on a feature branch, and suddenly a critical bug is reported on the main branch. With worktrees, you can:

  1. Add a new worktree for the main branch.
  2. Navigate to the new worktree and fix the bug.
  3. Commit and push the fix from the hotfix worktree.
  4. Return to your original worktree and continue working on your feature.

Before we see how to get started, here are some considerations to keep in mind:

  • Changes in one working tree don't affect others until they're committed and pulled.
  • It is not possible to have multiple worktrees on the same branch (each worktree can be on a different branch).
  • If you are dealing with a very large repository, be cautious of the amount of disk space being used (although all worktrees share the same .git directory to save disk space).

Now, onto the fun part!

Git worktree offers two main ways to create a new working tree:

  1. Creating a new branch: When you use git worktree add <path> without specifying a branch, Git does two things:
  • It creates a new branch named after the last part of the path you provided.
  • It checks out this new branch in the new worktree at the specified path.

Consider the following example:

$ git worktree add ../hotfix

This command creates a new branch called "hotfix" and sets up a new worktree for it in the "../hotfix" directory.

  1. Using an existing branch: If you want to work on an already existing branch in a new worktree, you can specify both the path and the branch name:
$ git worktree add <path> <branch>

Here's an example:

$ git worktree add ../feature-work existing-feature-branch

This creates a new worktree in the "../feature-work" directory, with the "existing-feature-branch" checked out.

These options give you flexibility in setting up new working areas, whether you're starting a new task or continuing work on an existing branch.

You can list all the worktrees you have created by typing:

$ git worktree list

Finally, to remove a worktree, you can use:

$ git worktree remove path/to/worktree

Git Worktree can be quite a complex command, as it offers many features. You can check the full documentation here.

Final Words

As you can see, there's a lot more to Git than just committing, pushing, and pulling! Git can be much more than just a version control system, and the advanced features we presented bring unique capabilities to the table, enhancing everything from debugging and conflict resolution to workflow customization and project organization.

With Git, there's always something new to learn — mastering it is a continuous journey. By familiarizing yourself with these lesser-known features, you will become a more proficient and versatile developer. Give them a try!

For more programming tips (not just about Version Control), don't forget to sign up for our newsletter below and follow Tower on Twitter and LinkedIn! ✌️

Your Download is in Progress…

Giveaways. Cheat Sheets. eBooks. Discounts. And great content from our blog!