228

Is there a way to execute Git commands against a repository without being in that repository?

For example something like this: git /home/repo log?

Please do not tell me to cd to it. I'm doing this via an exec call.

ntc2
  • 11,203
  • 7
  • 53
  • 70
Tower
  • 98,741
  • 129
  • 357
  • 507
  • 4
    Can't you just "cd /home/repo && git log" as your exec call? – Alex Howansky Aug 22 '11 at 15:46
  • I have some weird problems with it. I'm starting a new process, not really an exec, but I don't know much how they differ though. I find it easier to just find a parameter to specify the git directory. – Tower Aug 22 '11 at 15:55
  • 1
    possible duplicate of [Can I perform git operations (add/diff/commit) on files in a repository when my current directory isn't in the repository](http://stackoverflow.com/questions/3205867/can-i-perform-git-operations-add-diff-commit-on-files-in-a-repository-when-my) – Hilikus Jun 07 '15 at 20:51
  • 1
    Possible duplicate of [git pull while not in a git directory](http://stackoverflow.com/questions/5083224/git-pull-while-not-in-a-git-directory) – Trevor Boyd Smith Mar 22 '17 at 18:08
  • 1
    git --git-dir=/home/repo/.git log – Atiq Ur Rehman Jan 10 '19 at 11:37
  • 2
    The accepted answer is wrong. That will still make changes based on the current dir. You need to use `-C` - as answered by @calandoa - hence that answer having twice as many upvotes. – LaVache Jul 07 '20 at 02:40

6 Answers6

390

Use -C as the first argument to git:

git -C /home/repo log

Per the docs, the effect of this is:

-C <path>

Run as if git was started in <path> instead of the current working directory. ...

This is almost equivalent to --git-dir and --work-tree without appending the usual .git folder. However, the options --git-dir and --work-tree do not exist to access the repository from outside the work tree; they are used to move the .git somewhere else, and they are much more complicated to use in some cases.

For instance, to get the log of /home/repo/subdir only:

git -C /home/repo/subdir log .

or

git -C /home/repo log subdir

It is not possible to use log . with --git-dir or --work-tree. The path must be processed to extract the subpath relative to the top of the work tree, and even in that case, git will not recognize it as a path if you do not use the -- option, so the only possible way is:

git --git-dir /home/repo/.git log -- subdir

Furthermore, --work-tree does not work at all with the log subcommand with my version (git 1.9.1). It is just ignored:

git --git-dir /home/repo/.git --work-tree /home/repo/subdir log -- subdir
git --git-dir /home/repo/.git --work-tree /home/repo/whatever log -- subdir

I do not even understand if this is a bug or a feature... as usual with many git design choices.

Chris F Carroll
  • 11,146
  • 3
  • 53
  • 61
calandoa
  • 5,668
  • 2
  • 28
  • 25
  • 1
    `git stash` is another example of an subcommand which fails if `--git-dir` and `--work-tree` are used. – d5ve Apr 03 '16 at 21:48
  • 8
    The -C option was added in version 1.8.5 of git, which was released in 2013. – d5ve Apr 06 '16 at 04:22
  • 1
    -C worked better than --git-dir for me ... -C honours git config settings for the repo. Am running git version 1.9.5.msysgit.1 – Straff Aug 19 '16 at 03:34
  • @calandoa do we always need to specify the location from the root , one more thing if the name of the repo contain multiple words how do we put in in this code – Kasun Siyambalapitiya Dec 06 '16 at 16:48
  • 4
    Note: you need to pass the -C option to git and not to the subcommand (as correctly done by @calandoa in this answer). Calling `git -C /some/dir add .` would work as expected while `git add -C /some/dir .` would throw an error. Just something to be aware of to prevent confusing results. – pjvleeuwen May 27 '17 at 18:12
  • @Kasun Siyambalapitiya: The path may be relative. (git version 2.34.1) – rundekugel Oct 24 '22 at 10:59
116

Try:

git --git-dir=/home/repo/.git log

It is important to give the path all the way up to the .git directory of your repository. Otherwise you will get only an error message that says something like:

fatal: Not a git repository
DaveyDaveDave
  • 9,821
  • 11
  • 64
  • 77
max
  • 33,369
  • 7
  • 73
  • 84
  • 6
    This didn't work for me, since it showed all files of the commit as deleted. Seems like it is checking the commit but not the folder contents. Refer to @calandoa 's answer for better performance. – mxcd May 05 '19 at 14:43
  • 9
    Didn't work for me using the latest git, however using the -C option it worked, example: git -C /home/repo/.git log – D.Snap Sep 28 '19 at 01:40
  • 9
    this actually did not work as the po expected. why this is any accepted answer? This will use the current dir as work tree and use the specified .git for history, which is completely wrong. If you do not just show log, for example, `git status`. `-C` is the correct way to go. – Wang Mar 19 '20 at 18:11
  • 2
    It does not work as people in previous comments already said – drndivoje Feb 02 '21 at 12:57
18

In fact you need to use --git-dir and --work-tree together. Here is an example:

local [] Desktop: mkdir git
local [] Desktop: cd git
local [] git: touch README.txt
local [] git: git init
Initialized empty Git repository in /Users/albert/Desktop/git/.git/
local [] git: cd ..
local [] Desktop: git --work-tree=git --git-dir=git/.git add .
local [] Desktop: git --work-tree=git --git-dir=git/.git commit -a -m 'initial commit, called from outside the git directory'
[master (root-commit) ee951b1] initial commit, called from outside the git directory
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.txt
local [] Desktop: cd git
local [] git: git log --pretty=oneline
ee951b161053e0e0948f9e2a36bfbb60f9c87abe initial commit, called from outside the git di
alberto56
  • 2,997
  • 3
  • 28
  • 47
13

I have tried many times! I finally got it!

git -C dir --no-pager log --format='%an' -1 filename

do remember, please don't add .git to your

-C dir

penny chan
  • 769
  • 1
  • 10
  • 15
6

For any git command, you can do:

git --git-dir=<PATH-TO-REPO>/.git --work-tree=<PATH-TO-REPO> <git-command>

For example, if you want to do a git status:

 git --git-dir=/home/myrepo/.git --work-tree=/home/myrepo/  status

or if you want to check the branch the repo is in:

git --git-dir=/home/myrepo/.git --work-tree=/home/myrepo/  rev-parse --abbrev-ref HEAD
HosseyNJF
  • 491
  • 1
  • 6
  • 18
Paula
  • 61
  • 1
  • 1
3

This is similar to @max's answer. Unfortunately, --git-dir didn't do what I needed. edit In retrospect, another [previous] answer I hadn't read suggested using --work-tree. I'm not sure whether using environment or flags is more appropriate so I'll leave my answer in case someone finds use in it, but I'll be switching to use --work-tree / --git-dir.


There's two repos, one inside the other but not a submodule; the outer repo ignores it:

tools (outer repo)
  gcc/4.9.2 (inner repo)

What I wanted was the output of git rev-parse --show-prefix relative to the outer repo. Here's what I came up with (bash syntax; split across lines for readability):

prefix_dir=$(cd ..; git rev-parse --show-toplevel)
prefix_dir=$(GIT_WORK_TREE=${prefix_dir} git rev-parse --show-prefix)

When executed from within 4.9.2 it produces the string gcc/4.9.2.

Brian Vandenberg
  • 4,011
  • 2
  • 37
  • 53