A convention for organizing your GitHub repository clones

As a software engineer, cloning repositories using Git is a common task. Most devs just create a single projects directory and clone all repositories there. However, this approach does not scale well and can lead to organizational issues like name collisions and difficulty finding repositories.

Solution: The GitHub Tree structure

The GitHub Tree structure is a straightforward yet effective way to organize your repositories by mirroring the organization on GitHub. It helps establish a clear structure that scales as your collection grows.

The structure is as follows:

~/Developer
└── github
    └── <GitHub org / username>
        └── <GitHub repo name>
  1. ~/Developer

    Choose a top-level directory for all your coding-related activities.

    While I use ~/Developer, feel free to use a different path of your preference. On macOS, Developer is a special directory with a unique icon, making it appropriate for my usage.

  2. github

    Within the top-level directory, create a subdirectory named github. This indicates that everything inside mirrors GitHub, and allows you to use the Developer directory for other things.

    This is useful if you use other Git servers like GitHub Enterprise, GitLab, or Bitbucket. In my case, I used to use a private GitHub Enterprise server at work, so I had a github and github-work directory for each site.

  3. <GitHub org / username>

    Each GitHub org/user should have their own directory within the github directory.

  4. <GitHub repo name>

    The repository clone should be in a subdirectory named after the repository.

Cloning repositories

Your own repository

For your own repo, simply clone it to the appropriate directory:

Terminal
git clone git@github.com:my-user/my-repo.git ~/Developer/github/my-user/my-repo

Tip

If ~/Developer/github/my-user/ doesn’t exist yet, git clone will automatically create it for you.

Forked repository

When cloning forks, use the original namespace:

  1. Fork the repository on GitHub.

  2. Clone the forked version to the directory of the original org.

    For example, if contributing to vercel/next.js, clone my-fork/next.js to ~/Developer/github/vercel/next.js:

    Terminal
    git clone git@github.com:my-fork/next.js.git ~/Developer/github/vercel/next.js

    This ensures that your clone has the correct origin remote set up for pushing.

  3. Add the upstream remote as up (short for “upstream”):

    Terminal
    git remote add up git@github.com:vercel/next.js.git

    This way origin will point to your fork, and up will point to the original repo.

    You can pull in the latest changes from up:

    Terminal
    git pull up <branch-name>

This approach helps maintain a clear separation between your repos and forks.

Benefits of the GitHub Tree

By organizing your repositories with the GitHub Tree structure, you’ll enjoy several benefits:

GitHub mirror

  • You don’t have to think about how to organize your repositories; you’re simply following GitHub’s structure.
  • Avoid name collisions as GitHub ensures unique repository names within an org.

Finding code

  • Quickly locate any repository due to the familiar organization.
  • Easily grep across multiple repositories with the results clearly indicating repository paths.

Scoped Git configurations

If you’re a dev with both personal and work projects in the same environment, you may want to commit using your work email for repositories in the work org.

This setup allows you can configure this seamlessly in your top-level ~/.gitconfig by toggling the appropriate Git profile based on which directory you’re in.

Here’s an example of how to set up three different profiles based on the org:

~/.gitconfig:

# My default profile
[user]
	name = Hiroki Osame
	email = personal@email.com

# My profile for Org A
[includeIf "gitdir:~/Developer/github/org-a/"]
	path = ~/Developer/github/org-a/.gitconfig

# My profile for Org B
[includeIf "gitdir:~/Developer/github/org-b/"]
	path = ~/Developer/github/org-b/.gitconfig

Note, the above explicitly references a .gitconfig file in each org directory. To set this up, create a .gitconfig with the relevant configuration:

[user]
	name = Hiroki Osame
	email = email@company.com

Now, whenever you commit in your personal repositories, Git will use your personal email. And when you commit to repos in your work org, it will use your work email.

By setting up different configs for each org, you can easily switch between your personal and work-related projects, ensuring that your commits and contributions are associated with the correct identity.

Try it out!

Using the GitHub Tree structure for organizing repository clones can greatly streamline your workflow as a software engineer. It ensures a clear and scalable organization, eliminates name collisions, and simplifies finding repositories.

Give it a try, and let me know what you think!


Thanks for reading! Hope you'll stick around.
— Hiroki Osame
Open source Engineer. Living in Tokyo. Working at Square.