- 🛠 Git worktrees change how the
.gitdirectory works. This can break scripts that use hardcoded paths. - 🧭
git rev-parse --git-common-dirshows the main Git repo directory, even when you use worktrees. - ⚡ Scripts using
git rev-parseare more reliable and work better than those using hardcoded.git/paths. - 🔍 Knowing the Git directory structure helps with debugging, managing hooks, and automating tasks.
- 🛡 If
.git/is exposed by mistake in production, it can leak private project information and past changes.
Why Knowing the Git Directory Matters
Every Git repository has a hidden folder: the .git/ directory. It stores everything Git needs for versions, branches, settings, and other data. When you create a repo with git init, you make this folder, even if you don't realize it. But in more advanced setups, like with worktrees, or when using Git in CI/CD or scripts, simply thinking the .git/ folder is always in your current directory can cause problems. Knowing what the Git directory is, how it works, and how to find it using tools like git rev-parse and git-common-dir is key to using Git safely and correctly.
Looking at the .git Directory Structure
The .git/ directory is the main part of a Git repository. When you commit changes, switch branches, or push updates to a server, Git uses this directory for every step. Here are the main files and folders inside:
Main Files and Folders
HEAD: This points to the current commit or branch.config: This holds settings for the repo, like remotes and user info.refs/: This keeps track of all your branches (refs/heads/) and tags (refs/tags/).objects/: This holds compressed versions of everything Git tracks, such as file contents (blobs), folder structures (trees), and commits.hooks/: This contains scripts that run during different Git actions (for example, when you commit, merge, or push).
Here is what a typical .git/ folder looks like:
.git/
├── HEAD
├── config
├── description
├── hooks/
├── info/
├── objects/
├── refs/
Why this Structure Matters
This structure is basic. If you change these files by hand without knowing what they do, you can damage the repo. For example, changing HEAD directly can lead to checkout problems or lost commits. And again, deleting things from objects/ will break Git's history and references.
What Changes with Git Worktrees
Git Worktrees are a good feature, but not many people use them. They let you have several working directories at once, all using the same Git data. This helps a lot when you switch branches often or work on many things at the same time.
Worktrees Change What .git Means
In a normal repo, .git/ is just a directory. But in a worktree, .git becomes a file that points to another directory where the actual Git data is:
$ cat .git
gitdir: /path/to/main/.git/worktrees/my-feature
So, the .git file does not hold Git data itself. Instead, it points to a separate Git directory used only for that worktree. The main repo's data, like branches and staged commits, is still in what Git calls the "common dir."
Why This Is Important
This small change has big effects. Many tools, scripts, and even IDEs expect .git/ to be a directory. If they don't check for worktrees, they might crash or not work right. So, it is very important to get Git paths using git rev-parse in your code.
Using git rev-parse: Your Debugging Companion
git rev-parse is one of Git’s most useful internal commands. It's not as well-known as git log or git status, but it's a must-have for scripting or debugging.
Key Flags Explained
Here are the most helpful flags for understanding your Git setup:
--show-toplevel: This shows the main directory of your project.--git-dir: This shows the path to the.git/directory that is in use.--git-common-dir: This shows the path to the main Git directory that holds shared data for all worktrees.
Each one shows more about how Git sees your project's structure.
Example
Say you are in a worktree and want to find where commit objects actually live (which is the main .git/objects). Instead of looking through folders by hand, run this:
git rev-parse --git-common-dir
This shows the main Git directory, no matter if you use worktrees or symlinks.
Finding the .git Directory in Any Context
Git's internal parts mean the Git directory is sometimes not where you expect it to be, or even not what you expect it to be. When you write scripts or automate tasks, you must check the right paths.
Normal Case
In a normal setup, not using worktrees:
git rev-parse --git-dir
# Output: .git
git rev-parse --git-common-dir
# Output: .git
Everything matches because you are in the main repository.
Worktree Case
In a Git worktree:
git rev-parse --git-dir
# Output: /path-to/.git/worktrees/feature-1
git rev-parse --git-common-dir
# Output: /path-to/.git
Here, --git-dir points to a worktree's Git data. But --git-common-dir takes you back to the main Git data that all worktrees share. Knowing this difference is very important when automating tasks that involve Git structures.
Why –git-common-dir Matters
Say your Continuous Integration system runs tests in many Git worktrees at the same time. You keep some shared data in the repo’s main .git/config file. If your script simply reads from ./.git/config, it will miss the real file. This is because, in a worktree, .git is just a file, not a directory.
Instead, this command always tells you where shared Git data, like config, hooks/, and objects/, is:
git rev-parse --git-common-dir
This is very helpful for:
- Setting or reading global settings in scripts.
- Turning on or changing Git hooks with accuracy.
- Managing lock files or shared data in automated setups.
Scripting Git Directory Detection Automatically
For automation, hardcoding Git paths is a bad idea. Luckily, scripting with git rev-parse is easy and strong.
Bash Example
#!/bin/bash
GIT_COMMON_DIR=$(git rev-parse --git-common-dir)
echo "Repository Root Directory: $GIT_COMMON_DIR"
Python Example
import subprocess
def get_git_common_dir():
return subprocess.check_output(
['git', 'rev-parse', '--git-common-dir']
).decode('utf-8').strip()
print("Root Git Dir:", get_git_common_dir())
These methods work well when you write pre-commit linters, changelog tools, or version scripts that need a steady Git environment.
Are You Inside a Worktree?
You can check if you are inside a valid worktree by using:
git rev-parse --is-inside-work-tree
# Output: true or false
If this shows false, Git operations might not work as you expect.
And again, another helpful flag is:
git rev-parse --is-bare-repository
# Output: true or false
This helps when you work with remote bare repositories, which are often used on servers.
To see the .git entry’s format:
file .git
A normal repo will say "directory." But a worktree might say "ASCII text," which means it points to another place.
Uses That Rely on Git Directory Knowledge
Knowing the true Git directory is not just fun facts. It is actually useful in how you work:
- Running pre-commit hooks: Hooks must go in the main
.git/hooks/folder, not in a worktree. - Building CI/CD pipelines: Find exact branches, read settings, or detect tags as needed.
- Changelog or versioning script: Make sure scripts get data in the right Git context, especially with many branches and worktrees.
- System diagnostics: Find object files or references if something goes wrong and you need to fix it.
Knowing the different structures of .git lets you build smarter solutions that work in any environment.
Common Problems with Worktrees and Hardcoded Paths
When using Git tools or writing scripts, many developers just assume .git/ is a directory in their project folder. This works in simple cases, but it breaks when these things happen:
- 🧪 When using Git worktrees.
- 📤 When syncing projects across different operating systems (like Windows to WSL).
- 🔁 When symbolic links change folder setups.
- 🔄 When using submodules or repos inside other repos.
Instead of hardcoded assumptions, use git rev-parse --git-dir or --git-common-dir. This keeps your script correct and able to work anywhere.
Security Warning: Do Not Expose .git in Production
The .git/ folder holds your project's full history. If it gets exposed by accident, it can lead to:
- 🚨 Leaked login info (stored in settings, committed by mistake).
- 🗂 Full access to source code through the repo's history.
- 🧾 Showing private data (author emails, commit messages).
Good ways to do things include:
- Add
.git/to.gitignore(if you are packaging your repo). - Set up
.htaccessor your web server to block.git/access. - Make sure build scripts or Docker images do not include
.git/.
For public websites, think of .git/ as dangerous: look at it, but do not touch it.
A Devsolus Story: Regex, Worktree Failures, and a Fix
A junior developer in the Devsolus community tried to make commit hooks with a simple bash script. The script looked for .git/hooks/ to install and manage hooks. It worked until the team started using worktrees.
The tool crashed on the first day. Hooks were not found anymore. Scripts failed without a warning. Builds stopped working.
The developer saw the problem, found git rev-parse --git-common-dir, changed the hardcoded path to find it automatically, and the problem went away. The fix was simple, but knowing the problem was important.
Advanced git rev-parse Tricks
Besides finding directories, git rev-parse helps you look inside Git. Some advanced uses include:
Get the Current Branch Name
git rev-parse --abbrev-ref HEAD
Get the HEAD Tree Object
git rev-parse HEAD^{tree}
Get Full Commit Hash
git rev-parse HEAD
These methods help if you are building your own tools, like Git GUIs, changelog tools, or branch logic.
Mastering Your Git Environment
Knowing how Git sets up its working space—from .git/ to --git-dir to --git-common-dir—will make you a quicker, better, more dependable developer. Tools like git rev-parse give you a steady, future-proof way to handle even the hardest repository setups.
Here is what to do next:
- Use
git rev-parsein every script, shell, or CI tool that works with Git. - Change all hardcoded
.git/references. - Test what you know in projects with worktrees or submodules.
- Make your workflows work anywhere, be safe, and ready for the future.
Learn the directory, and you learn the repo.
Citations
Chacon, S., & Straub, B. (2014). Pro Git (2nd ed.). Apress.
Google Open Source Blog. (2021). Improving Git Worktree Performance. Retrieved from https://opensource.googleblog.com
Loeliger, J., & McCullough, M. (2012). Version Control with Git (2nd ed.). O'Reilly Media.