Danny Sauer <danny@xxxxxxxxxxxxxx> writes: > That's feedback I was looking for - what's the "right" way to get the > path to the file. My knee-jerk reaction is that you SHOULDN'T have to do anything special to "get the path". I do not have the code in front of me (this is my "down" week after all), so let me give the general outline of how to reason about this, with the knowledge of code evolution of the system. In the beginning, Git worked only from the top level of the working tree. If you have your project in ~/myproject with a file "f" in a directory "d", that file is ~/myproject/d/f", and you would do $ cd ~/myproject $ git add d/f to add it. If Git wanted to access the index, it just accessed ".git/index" as a relative path. If Git wanted to access a file at the top of the working tree, say ".gitignore", it just accessed ".gitignore" as a relatlvei path. Because it only worked from the top. Then we added a support for running Git from a subdirectory, so that you can say "cd ~/myproject/d && git add f". In order to keep the existing code that wants to access the index as ".git/index" and wants to access the top-level ".gitignore" as ".gitignore" working, the support to run Git from a subdirectory is designed this way: - Each main program of subcommand (e.g. cmd_log()) receives a parameter "prefix", which tells what subdirectory you were in when you started Git. - Before running the main program of subcommand, Git chdir(2)s up to the top level of the working tree. - The main program of subcommand receives the command line from the user intact. It is responsible for prepending the prefix to the path the user gave it from the command line. So if you did "cd ~/myproject/d && git add f", Git goes up to "~/myproject", passes argv=("f", NULL) and prefix="d/" to cmd_add(). Adding to the index wants to read and update the index, which is still done by opening ".git/index" (relative to the toplevel as before), and inspecting the top-level .gitigore file is done by opening ".gitignore" (relative to the toplevel as before). And the cmd_add() forms the path "d/f" by using the prefix "d/" and the user-supplied pathname "f". When we first added a support for having the (equivalent of) ".git/" directory outside the working tree by setting GIT_DIR environment variable, again, you can only use Git from the top-level of the working tree. Instead of "~/myproject/.git", you can keep your repository metainformation in say "~/mypro.git/" and point at it with GIT_DIR environment variable, and said $ export GIT_DIR=~/mypro.git $ cd ~/myproject $ git add d/f Later we also added GIT_WORK_TREE environment variable to be used together with GIT_DIR so that you can start from ~/myproject/d, very similarly to how you worked from a subdirectory without these environment variables, i.e. $ export GIT_DIR=~/mypro.git GIT_WORK_TREE=~/myproject $ cd ~/myproject/d $ git add f The way this support was added was to go to the top-level of the working tree (i.e. "~/myproject" in this example) and passing the prefix (i.e. "d" in this example). Notice that in all of the above configurations, if a Git command knows a path to something that is relative to the top of the working tree (e.g. ".git/index" in the ancient Git, ".gitignore" at the top-level that governs the entire working tree, or ".mailmap"), it should just be able to open that path without asking "where is the top of the working tree?". So if your directory arrangement is a variation of these basic configurations supported, e.g. if your git directory is ~/myproject/.git and your working tree is ~/myproject, and you use the GIT_DIR and GIT_WORK_TREE to point at them, regardless of which subdirectory of $GIT_WORK_TREE you started with, Git should already have done chdir(2) to ~/myproject/ before it starts cmd_log(), and it should be able to just open and read ".mailmap" (of course, it needs to limit itself to do so only when it is working with a repository with a working tree). If your arrangement is even more exotic, e.g. you have these two variables set, and then are running from OUTSIDE the working tree, my knee-jerk reaction is that you should get your head examined, as it is totally unclear what "git add foo" would mean if you did this: $ export GIT_DIR=~/myproject/.git GIT_WORK_TREE=~/myproject $ cd ~/myproject/../somewhere/else $ git add foo But it should still "work" in the sense that the above command should notice that you are trying to add "../somewhere/else/foo" to the index, which is obviously nonsense, and die with a message. Similarly, if you replace "git add foo" with "git log", it still should work in the above, i.e. $ export GIT_DIR=~/myproject/.git GIT_WORK_TREE=~/myproject $ cd ~/myproject/../somewhere/else $ git log If Git is not chdir(2)ing to ~/myproject before calling cmd_log() in the above (again, this is my down week so I didn't and will not check with the code myself), we may want to call that a bug and fix it, so that you do not have to do anything special to get to the path of ".mailmap" that is at the top-level.