7 Git Mistakes a Developer Should Avoid
August 2023 by Bruno Brito

7 Git Mistakes a Developer Should Avoid

In this blog post, we will explore common Git mistakes and bad practices that every developer should be aware of and, more importantly, avoid.
In essence, this post is about what you shouldn't do in Git!

Git is our bread and butter, and we think it's an incredibly powerful tool — but it doesn't teach you how it should be used. That's why, in this guide, we will focus on addressing the 7 most prevalent mistakes that we have observed among both new and experienced developers when using Git.

By learning from these mistakes and adopting best practices, we are certain that you will become a more skilled and confident developer... as well as a more popular team member! 😁

Let's jump straight in!

1. Committing Large and Unrelated Changes Together

After a long day of work, adding every changed file to a single commit can be tempting. You're perfectly aware of the changes you made, so you happily add every file from the staging area and write a commit message.

This is a classic Git bad practice because your teammates will struggle to quickly grasp the changes you've made. The same can be said about your future self, 6 months from now, when you're trying to understand the purpose and intent behind that commit.

While this is the most significant disadvantage, there are other aspects that you should also consider:

  • Reverting a commit becomes problematic: If you need to undo a specific change within the commit, reverting the entire commit will revert all the changes, including the ones you might want to keep.
  • Code reviews become a chore: Code reviews are essential for maintaining code quality and catching potential issues. When changes are unrelated, code reviews become less effective, as reviewers may need to spend more time understanding the changes and their context.
  • Merging branches can lead to more conflicts: Combining unrelated changes can often result in confusion, especially when multiple files have been modified. In addition, the likelihood of encountering merge conflicts also increases.

To avoid this, you should commit small and focused changes. This approach, known as "Atomic Commits," suggests that commits should be small and focused solely on a single topic. This does not mean a commit should only include a single changed file, but that it should represent a single logical change or fix.

You should feel motivated to make multiple commits so that your Git history remains clear. Every developer, including yourself, will appreciate the effort you put into doing so!

Staging Chunks or Lines of Code

Instead of git add -A, you could type git add <filename> to add a single file. But you can go one step further and stage just portions or even single lines of changed code.

This can be achieved with git add -p <filename>, where Git will break down the file into chunks (also called "hunks") and ask if you would like to stage that section.

This process is much easier if you're using a Git client like Tower, which is available for Mac and Windows. Staging chunks or individual lines only require a few clicks.

Staging Chunks and Lines in Tower

Too Late? Interactive Rebase to the Rescue!

If you have already made the mistake of combining unrelated changes, you can use interactive rebase to split the commit into smaller, meaningful commits.

Interactive Rebase lets you rearrange, edit, combine, and delete commits, so it's a very powerful command in your Git toolkit. Just make sure you're performing these actions before pushing to the remote repository!

In the command line, you can launch the Interactive Rebase editor by typing git rebase -i HEAD~n, where 'n' is the number of commits you want to go back from the current HEAD. For example, if you want to modify the last 4 commits, you should use HEAD~4.

Your default text editor will open with the list of commits you chose. All of them will have the "pick" keyword prepended, which stands for "keeping" the commit as it is. You can change this word to "squash" or "fixup" to combine commits, "reword" to edit the commit message, or "edit" to split commits and make modifications, which is what you're looking for in this case.

After you're done with the changes, you can save the document. If you used the "edit" command, Git will pause at those points to allow you to make changes. When everything is looking good, you can stage them again and type git rebase --continue.

This is another Git operation where visual aid comes in handy, and Tower can be a powerful companion for this task.

You could use Tower's drag and drop to move commits around (or squash them), but in this case, we're looking to edit the commit. This is as easy as right-clicking the commit and choosing "Edit".

Tower — Edit Commit Message
Tower — Edit Commit Message

Tower's Merge UI will launch, allowing you to conveniently stage each changed file again.

Tower — Merge UI
Tower — Merge UI

2. Neglecting to Write Descriptive Commit Messages

Similar to the previous point, many developers underestimate the power of a carefully written commit message. Our community jokingly shared with us some funny commit messages they've written or encountered in the past, such as:

  • "Please fix later"
  • "Bugfix (Second try)"
  • "Magic, do not touch!!!"
  • "This is the ninth attempt at rebasing"
  • "I don't understand how this works, just don't revert this one"

While commit messages like these provoke a chuckle, they don't provide the necessary context to quickly determine what that commit actually contains. This raises a problem for any developer working on the project, as they now need to inspect the changes (let's at least hope the commit author followed the previous advice!).

A lot can be said about a good commit message, which is why we wrote this guide on how to write the perfect commit message. In a nutshell, providing context is key — referencing files, commits, and issues can be helpful to understand the decisions behind each update to the project.

Tower makes this action even easier, as you can simply type "/" in the subject or body fields to quickly reference files, commits, and issues.

Tower — Commit Composing

Many teams also adhere to a specific convention when it comes to character length and wrapping mode. Tower also allows users to customize these settings according to their preferences.

Tower — Editor Settings
Tower — Editor Settings

3. Ignoring .gitignore

The .gitignore file, as the name suggests, is used to exclude certain files from being tracked by Git. Files such as build artifacts, log files, temporary files, IDE or platform-specific files, and dependencies may clutter your repository and slow down performance. As a general rule, it is advisable to exclude most automatically generated files from Git.

While it is highly recommended to define the list of ignored files and folders at the beginning of your project (even before making your first commit), it is important to regularly review this file to account for any new scenarios that may arise.

Teams often underestimate the importance of this review process, but its careful maintenance can provide significant long-term benefits. By managing ignored files in a centralized manner, the .gitignore file ensures consistency across the team, rather than having each developer configure their own local ignore rules.

4. Not Cleaning Up Old Branches

Most teams have adopted the Git Feature Branch workflow. One drawback of this approach is that, after the feature branch is merged into the main branch, the feature branch often remains in the repository, even though there are no longer any unique commits associated with it.

After some time, it will be impossible for you (or your colleagues) to determine if that branch is safe to delete. Questions such as "Has it already been merged? Is someone still working on this?" will come to mind. In a large organization with ongoing development projects, it is common for branches to become stale over time and for your repository to become bloated.

To avoid this, you can check if both local branches contain a certain commit, as suggested by this article — but there are pitfalls, as sometimes Git may not be able to detect if a specific branch has been fully merged.

Better yet, you can use Tower to list all the local branches and filter by "Fully Merged" to clean up your repository without any hesitation!

Cleaning Up Merged Branches in Tower

5. Using Force Push on Shared Branches

There will be times when your local repository is not in sync with its remote counterpart. You try pushing and... it doesn't work.

No problem, this has happened before. I will simply use "Force Push" 😈

Force Push is a very powerful command that should be approached with caution. Since it overwrites the remote repository with whatever's in your local project, you may erase commits added by your colleagues in the meantime. It's also quite likely that your colleagues are working on the old commit history, which will no longer be current.

A safer instruction would be to type git push --force-with-lease instead. This option is actually the default choice for many teams as a fail-safe measure. The command will fail if there have been changes to the remote branch, ensuring that everyone's work remains intact. It serves as a reminder to perform a git fetch before pushing.

This is also the case in Tower: if you try to force push and there is already a newer commit on the remote, Tower will display a warning to inform you before proceeding with your changes.

Tower — Force Push with Lease
Tower — Force Push with Lease

6. Storing Sensitive Information in the Repository

Storing sensitive information in a Git repository poses a considerable security risk. When sensitive data, such as passwords, API or SSH keys, private keys, or personal details, is added to version control, it becomes accessible to anyone with access to the repository.

At a minimum, this means that your project collaborators will have access to this data. In a worst-case scenario, if the repository is made public on a code hosting platform like GitHub, it means that anyone in the world could potentially have access to it.

To avoid this, you should use Environment Variables and include any sensitive files or directories in the previously mentioned .gitignore file to prevent them from being committed accidentally.

You should also make an effort to periodically review your Git history to ensure that no sensitive information has been wrongfully uploaded. Educating new team members about the importance of not storing sensitive information in version control is also a good idea.

Oh No, Too Late! Now What? 😨

If the data is already being tracked in Git, the first action you should take is to change every password and API key.

The next step should be to remove any traces of sensitive data. GitHub has a comprehensive guide on this issue, which suggests using one of two tools: git-filter-repo or BFG Repo-Cleaner.

This is another compelling reason to make small, granular commits and use a GUI like Tower. With the additional visual aid it provides, it's very easy to quickly review the content of each file that is being added, deleted, or modified with each commit.

7. Storing Large Binary Files

Another common bad practice in Git is using it as a backup tool to store every file related to the project. This includes large binary files such as videos, audio tracks, or Photoshop files.

As a result, your repository will become bloated and cloning it will take longer and longer. Thankfully, there is a solution for this issue: Git LFS.

Git Large File Storage was created with the specific purpose of managing versioning for large files. This is actually an extension of Git, so you will need to download and install the CLI extension on your machine. Once installed, it will also need to be added to your repository by typing git lfs install.

Once that is completed, you just need to list the files or extensions that LFS should track (similar to the example provided below) and then add the .gitattributes file to Git. This is the file that LFS creates to keep track of the file names and patterns.

$ git lfs install
$ git lfs track "*.wav"
$ git lfs track "images/*.psd"
$ git lfs track "videos"
$ git add .gitattributes

Tower has full LFS support. In fact, you don't even have to install the extension manually on your local computer! You can easily enable it by accessing the repository's settings.

Tower — Enable LFS
Tower — Enable LFS

Once enabled, you can right-click any large, unwanted file (or file type) to track it.

Tower — Tracking All Files With Type .MP4
Tower — Tracking All Files With Type .MP4

Final Words

In this article, we've covered a comprehensive list of common worst practices in Git, along with advice on how to avoid them. Mastering Git commands is essential for developers, but it is equally important to steer clear of these harmful practices.

By following these 7 commandments, you are already on the right track to maintaining a healthy repository that encourages seamless collaboration.

We hope that you found this post useful. For more programming tips, 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!