push-f.com

Tracking .git/config files centrally with git

How do you start working on a remote git repository? You clone it from an URL with git clone <url>. Great! Now let’s say a month later you want to clone the same repository on a different machine. What was the URL again?

Over the years I have amassed so many git repositories with varying upstream servers that this has become a regular struggle for me. To make things worse I also use different git identities (name and email) for work and hobby projects. So after I have somehow acquired the URL I also need to remember to set up the right git identity.

Surely there must be a better way?

write down your remote URLs in a txt file

Then the URL changes and I forget to update the file.

completely sync your repositories with rsync

I fear forgetting to pull or push and loosing data.

use git submodules to avoid having to remember URLs

Since submodules are meant for dependencies they always point to a specific commit, which we don’t want … we always want the latest version.

global git config with path-based conditional includes to automatically configure git identity

This restricts where you can put your .git directories and identity changes made with git config are not synchronized (they just override the global config).

Introducing git config linker (gcl)

The solution I eventually came up with is to:

  1. have all repositories in one directory (I use ~/repos)
  2. move the config files of the repositories to a gitconfigs git repo, leaving a symbolic link behind

This means that all of your repository git configurations are tracked centrally (including all git remotes and your git identity). To make this convenient I wrote a Python script which grew to 200 lines and has the following usage:

git config linker (gcl):

 gcl status            check the status of the directories in .

 gcl link <repo>...    move <repo>/.git/config to gitconfigs/<repo>
                       (leaving a symlink behind)

 gcl clone             list all configs that are not cloned

 gcl clone <config>... clone a repository using gitconfigs/<config>

 gcl mv <src> <dest>   rename a repo and its config and update the symlink

 gcl unlink <repo>...  undo "gcl link <repo>"
                       (only needed if you want to stop using gcl)

You can check out the script at https://git.push-f.com/tools/tree/gcl

It also shows you which repositories have no remotes, unpushed commits or a dirty working tree.

Example session

Setup:

$ mkdir ~/repos
$ cd ~/repos
$ git init gitconfigs

Let’s clone a repo:

$ git clone https://git.push-f.com/tools
$ gcl status
unlinked repos:
    (link with "gcl link <name>...")

    gitconfigs NO REMOTE
    tools

Let’s link the repo:

$ gcl link tools
$ gcl status
unlinked repos:
    (link with "gcl link <name>...")

    gitconfigs NO REMOTE, DIRTY

linked repos:

    tools

Let’s simulate cloning the repo on a different machine:

$ rm -r tools
$ gcl clone
uncloned configs:
    (clone with "gcl clone <name>...")

    tools

gcl clone lists all configs that are not cloned.

$ gcl clone tools
$ gcl status
unlinked repos:
    (link with "gcl link <name>...")

    gitconfigs NO REMOTE, DIRTY

linked repos:

    tools