5 Hidden Git Tips for Java Developers

Photo of Luqman Saeed by Luqman Saeed

Git, the weirdly named version control system developed by Linus Torvalds,  is an amazing tool for developers, and us Java developers are no exception. While most of us are familiar with the basics like git commit, git push and git pull, Git has a lot of lesser-known features that can significantly improve your workflow. In this post, we’ll explore five hidden Git tips tailored specifically for Java development. These tips will help you manage your codebase more efficiently, debug issues faster and collaborate more effectively. Let’s go!

1. Use Git Bisect To Find The Commit That Introduced A Bug

Java applications often have complex codebases, and tracking down the exact commit that introduced a bug can feel like finding a needle in a haystack, or rather a snowflake in a blizzard? Anyway, git bisect is a powerful git feature that conducts binary search through your commit history to identify the problematic commit.

How It Works:

The git bisect command helps you find the exact commit that introduced a bug by performing a "binary search" through your commit history. It works as follows:

  1. Start the Bisect Process:
    Begin by telling Git you want to start the bisect process:
    git bisect start
  2. Mark the Current Commit as Bad:
    If the bug exists in the current commit (the one you're on right now), mark it as "bad":
    git bisect bad
  3. Mark a Known Good Commit:
    Find a commit from the past where the bug did not exist (e.g., a commit from a week ago). Mark it as "good" by providing its commit hash:
    git bisect good <commit-hash>
  4. Git Checks Out a Middle Commit:
    After marking the good and bad commits, Git will automatically check out a commit in the middle of the range between them. This is where the "binary search" begins.
  5. Test the Code:
    Test your Java application to see if the bug exists in this middle commit:
    • If the bug is present, mark the commit as bad:
      git bisect bad
    • If the bug is not present, mark the commit as good:
      git bisect good
  6. Repeat the Process:
    Git will continue checking out commits in the middle of the new range (based on your good/bad marks). Keep testing and marking commits until Git identifies the exact commit that introduced the bug.
  7. Finish the Bisect Process:
    Once Git finds the problematic commit, it will display the commit hash and details. You can then end the bisect process by running:
    git bisect reset

Why This is Helpful:

  • Instead of manually checking every commit, git bisect automates the process of narrowing down the source of a bug.
  • It’s especially useful in large Java projects, like legacy Java EE (J2EE) applications with long commit histories, where finding the buggy commit manually would be time-consuming.

2. Use git blame to Understand Code Changes

When working on a large Java codebase, it’s common to come across code that’s difficult to understand. git blame is a handy command that shows you who last modified each line of a file and when. I think this command could have been named something else than ‘blame’, but I am digressing. 

How It Works:

Run the following command to see the commit hash, author and date for each line in a file:

git blame <file-name>

For example:

git blame src/main/java/com/example/MyClass.java

Pro Tip:

Use the -L flag to focus on specific lines. For example, to see who modified lines 50 to 60:

git blame -L 50,60 src/main/java/com/example/MyClass.java

Why This Is Helpful:

  • Java codebases, like those developed on the Jakarta EE Platform,  often involve multiple developers. git blame helps you understand the context behind changes, making it easier to debug or refactor code.

3. Use git stash to Temporarily Save Unfinished Work

We often switch between tasks, such as fixing a bug while working on a new feature. git stash allows you to temporarily save your changes without committing them, so you can switch branches or tasks cleanly. Think of git stash as a temporary shelf for your code changes.

How It Works:

  1. Stash your changes:
    git stash
  2. Switch branches or work on another task.
  3. Reapply your stashed changes when you’re ready:
    git stash pop

Pro Tip:

Use git stash list to view all stashes and git stash apply <stash-id> to apply a specific stash.

Why It’s Great:

  • Java projects often involve multiple branches for features, bug fixes and releases. For example, take a look at the GitHub repo of Payara Server Community. git stash helps you manage unfinished work without cluttering your commit history.

4. Automate Clean-ups with git clean

Java projects generate a lot of build artifacts (e.g., .class files, target/ directories). Over time, these files can clutter your workspace. The git clean command removes untracked files, helping you keep your workspace clean.

How It Works:

  1. Preview files that will be deleted (dry run):
    git clean -n
  2. Delete untracked files:
    git clean -f
  3. Delete untracked directories as well:
    git clean -fd

Pro Tip:

Use git clean -x to remove ignored files (e.g., .idea/ or .classpath) too.

Why It’s Great:

  • Java build tools like Maven and Gradle generate a lot of temporary files. git clean ensures your workspace stays tidy and free of unnecessary artifacts.

5. Use git hooks to Automate Java-Specific Workflows

Git hooks are scripts that run automatically before or after Git events like commits, pushes or merges. We can use git hooks to enforce coding standards, run tests or trigger builds.

How It Works:

  1. Navigate to the .git/hooks directory in your repository.
  2. Create a hook script (e.g., pre-commit or post-merge).
  3. Make the script executable:
    chmod +x .git/hooks/pre-commit

    Add your custom logic. For example, a pre-commit hook to run unit tests:


#!/bin/sh
mvn test
if [ $? -ne 0 ]; then
 echo "Tests failed. Commit aborted."
 exit 1
Fi

This is a simple pre-commit hook that aborts a commit if tests fail. You could also automate code formatting with tools like Spotless in a similar pre-commit hook.

Why It’s Helpful:

  • Every non-trivial Java project will often require strict adherence to coding standards and thorough testing. Git hooks automate these checks, ensuring high code quality.

Bonus Tip: Use git checkout - to Switch Between Branches Quickly

We often work on multiple branches simultaneously, such as feature, bugfix and release branches. Such is the nature of all enterprise Java applications. Switching between these branches can be cumbersome if you have to type out the full branch name each time. Fortunately, Git provides a shortcut to quickly switch back to the previous branch you were on.

How It Works:

The git checkout - (the dash symbol) command allows you to switch to the last branch you were working on without needing to specify its name.

For example:

  1. You’re currently on the feature-branch:
    git checkout feature-branch
  2. You switch to the main branch to pull the latest changes:
    git checkout main
  3. After pulling changes, you want to return to feature-branch. Instead of typing the branch name again, simply use:
    git checkout -

This command will switch you back to feature-branch instantly.

Why It’s Great for Java Developers:

Java projects often involve working on multiple branches for different tasks, such as feature development, bug fixes and hotfixes. The git checkout - command saves time and reduces the risk of typos when switching branches, making your workflow more efficient.

Extended Bonus Section: Combining git log --grep and git checkout -

You can combine the power of git log --grep and git checkout - to streamline your workflow even further. For example:

  1. Use git log --grep="bugfix" to find a commit related to a specific bugfix.
  2. Check out the commit or branch where the bugfix was implemented.
  3. After reviewing the changes, switch back to your previous branch using git checkout -.

This combination allows you to efficiently navigate through your commit history and return to your original context without losing track of your work.

Conclusions

Git is a versatile tool with many hidden features that can significantly enhance your productivity as a Java developer. Whether you're debugging with git bisect, managing unfinished work with git stash, or quickly switching branches with git checkout -, these tips can help you work smarter, not harder. Incorporating these techniques into your daily workflow will help you manage your Java projects better and focus on writing great code. Of course git is not limited to just Java projects. These tips apply to any project that you are tracking with git.

So now, what is your favorite Git tip? Share it in the comments below!

Related Posts

Comments