Close

Git - Specifying custom Git Repository and Work Tree locations

[Updated: Dec 3, 2018, Created: Dec 2, 2018]

Git-Repository and Work-Tree Locations

The git-directory is where the repository resides (the .git folder as we saw in previous examples).
The work-tree has our source code which we want to be managed by git.

In previous examples we used the same locations for both source code and git directory.

Specifying custom locations

The Git repository folder can be stored separately from the the work tree folder. There are two ways to do that:

  • By using options --git-dir and --work-folder of git command. These have to be used with all git operations.
  • By setting environment variables: GIT_DIR and GIT_WORK_TREE.

Command to find repository locations

The command to find git directory:

git rev-parse --git-dir

The command to find work-tree directory:

git rev-parse --show-toplevel

The command rev-parse (rev stands for revision) can be used for multiple purposes.

Examples

Using '--git-dir' and '--work-tree' options

Joe@jpc MINGW64 ~
$ mkdir example

Joe@jpc MINGW64 ~
$ cd example

Joe@jpc MINGW64 ~/example
$ git  --git-dir my-repo --work-tree project init
Initialized empty Git repository in C:/Users/Joe/example/my-repo/

Joe@jpc MINGW64 ~/example
$ ls -la
total 52
drwxr-xr-x 1 Joe 197610 0 Dec  2 02:49 ./
drwxr-xr-x 1 Joe 197610 0 Dec  2 02:42 ../
drwxr-xr-x 1 Joe 197610 0 Dec  2 02:49 my-repo/

Git created our custom repository folder (my-repo) but there's no work-tree folder (project). We have to create that manually.

Git actually saves work-tree information in the config file:

Joe@jpc MINGW64 ~/example
$ cat my-repo/config
[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        worktree = C:/Users/Joe/example/project
        ignorecase = true

Let's create our work-tree directory and check the status there:

Joe@jpc MINGW64 ~/example
$ mkdir project

Joe@jpc MINGW64 ~/example
$ cd project

Joe@jpc MINGW64 ~/example/project
$ git status
fatal: not a git repository (or any of the parent directories): .git

Joe@jpc MINGW64 ~/example/project
$ git --git-dir ../my-repo status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Note that we had to provide our custom repository location where git could also gets the work-tree location (project) from config file.

Let's add some files to git.

Joe@jpc MINGW64 ~/example/project
$ echo line1 > test.txt

Joe@jpc MINGW64 ~/example/project
$ git --git-dir ../my-repo status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        test.txt

nothing added to commit but untracked files present (use "git add" to track)

Joe@jpc MINGW64 ~/example/project
$ git --git-dir ../my-repo add test.txt
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory

Joe@jpc MINGW64 ~/example/project
$ git --git-dir ../my-repo status
No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   test.txt

In all above operations we had to specify --git-dir.

If we go to the repository folder then git will have enough info to link work-tree to the repository (by looking at config file's worktree value). That means we don't have to specify any extra option there. Let's try that we a new file:

Joe@jpc MINGW64 ~/example/project
$ echo line2 > test2.txt

Joe@jpc MINGW64 ~/example/project
$ cd ../my-repo/

Joe@jpc MINGW64 ~/example/my-repo (master)
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        test2.txt

nothing added to commit but untracked files present (use "git add" to track)

Joe@jpc MINGW64 ~/example/my-repo (master)
$ git add test2.txt
warning: LF will be replaced by CRLF in test2.txt.
The file will have its original line endings in your working directory

Joe@jpc MINGW64 ~/example/my-repo (master)
$ git commit -m 'commit 2'
[master f51b668] commit 2
 1 file changed, 1 insertion(+)
 create mode 100644 test2.txt

Joe@jpc MINGW64 ~/example/my-repo (master)
$ git log
commit f51b6683f9f8039ee7565f56eef62d70637277d4 (HEAD -> master)
Author: Joe <joe@example.com>
Date:   Sun Dec 2 03:08:17 2018 -0600

    commit 2

commit 007a6a1af9acc66d7ea5924c951b13e8f0967d26
Author: Joe <joe@example.com>
Date:   Sun Dec 2 03:05:31 2018 -0600

    first commit

Note that once we are in the repository folder git show branch name '(master)' in cyan color.

When we use --git-dir option then we can be at any location to run the commands:

Joe@jpc MINGW64 ~/example/my-repo (master)
$ cd /

Joe@jpc MINGW64 /
$ git --git-dir ~/example/my-repo status
On branch master
nothing to commit, working tree clean

Joe@jpc MINGW64 /
$ git --git-dir ~/example/my-repo log
commit f51b6683f9f8039ee7565f56eef62d70637277d4 (HEAD -> master)
Author: Joe <joe@example.com>
Date:   Sun Dec 2 03:08:17 2018 -0600

    commit 2

commit 007a6a1af9acc66d7ea5924c951b13e8f0967d26
Author: Joe <joe@example.com>
Date:   Sun Dec 2 03:05:31 2018 -0600

    first commit

Using git rev-parse commands (only works when used inside git repository unless we specify --git-dir there too):

Joe@jpc MINGW64 ~/example/my-repo (master)
$ git rev-parse --git-dir
.

Joe@jpc MINGW64 ~/example/my-repo (master)
$ git rev-parse --show-toplevel
C:/Users/Joe/example/project

Joe@jpc MINGW64 ~/example/my-repo (master)
$ cd ..

Joe@jpc MINGW64 ~/example
$

$ git --git-dir my-repo rev-parse --git-dir
my-repo

Joe@jpc MINGW64 ~/example
$ git --git-dir my-repo rev-parse --show-toplevel
C:/Users/Joe/example/project

Using GIT_DIR and GIT_WORK_TREE environment variables

Joe@jpc MINGW64 ~
$ mkdir example2


Joe@jpc MINGW64 ~
$ cd example2

Joe@jpc MINGW64 ~/example2
$ export GIT_DIR=~/example2/my-repo

Joe@jpc MINGW64 ~/example2
$ export GIT_WORK_TREE=~/example2/project

Let's init our repository (we can do that from anywhere after setting the environment variables)

Joe@jpc MINGW64 ~/example2
$ git init
Initialized empty Git repository in C:/Users/Joe/example2/my-repo/


Joe@jpc MINGW64 ~/example2 (master)
$ ls -la
total 52
drwxr-xr-x 1 Joe 197610 0 Dec  2 15:34 ./
drwxr-xr-x 1 Joe 197610 0 Dec  2 15:17 ../
drwxr-xr-x 1 Joe 197610 0 Dec  2 15:34 my-repo/

Let's read git local config file:

Joe@jpc MINGW64 ~/example2 (master)
$ cat my-repo/config
[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        worktree = C:/Users/Joe/example2/project
        ignorecase = true

This time also git added 'worktree' variable.
So if we unset the two environment variables, we can still use our repository via --git-dir option.

Let's use git rev-parse command (can be used from anywhere given that the two environment variables are set):

Joe@jpc MINGW64 ~/example2 (master)
$ git rev-parse --git-dir
C:/Users/Joe/example2/my-repo

Joe@jpc MINGW64 ~/example2 (master)
$ git rev-parse --show-toplevel
C:/Users/Joe/example2/project

Let's add some files:

Joe@jpc MINGW64 ~/example2 (master)
$ mkdir project

Joe@jpc MINGW64 ~/example2 (master)
$ echo test > project/test.txt

Joe@jpc MINGW64 ~/example2 (master)
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        test.txt

nothing added to commit but untracked files present (use "git add" to track)

Joe@jpc MINGW64 ~/example2 (master)
$ git add test.txt
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory

Joe@jpc MINGW64 ~/example2 (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   test.txt


Joe@jpc MINGW64 ~/example2 (master)
$ git commit -m 'first-commit'
[master (root-commit) 592d690] first-commit
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

If we go into repository directory:

Joe@jpc MINGW64 ~/example2/my-repo (GIT_DIR!)
$

Git tells us at we are inside git-dir by showing (GIT_DIR!) in cyan color.

See Also