What's the ".git/gitdir" file?
Hello,
When a ".git" file points to another repo, a ".git/gitdir" file is created in that repo.
For example, running
$ mkdir repo-a repo-b
$ cd repo-a
$ git init
$ cd ../repo-b
$ echo "gitdir: ../repo-a/.git" > .git
$ git statusresults in a file "repo-a/.git/gitdir" that contains
$ cat repo-a/.git/gitdir
.gitI don't see this file mentioned in the gitrepository-layout manpage, and my searches haven't turned up any information on it. What's the purpose of ".git/gitdir"? Are there cases where it will contain something other than ".git"?
Thanks.
--
Kyle
git version 2.6.1
Quoted 19 lines · Kyle Meyer
Hello,
When a ".git" file points to another repo, a ".git/gitdir" file is created in that repo.
For example, running
$ mkdir repo-a repo-b $ cd repo-a $ git init $ cd ../repo-b $ echo "gitdir: ../repo-a/.git" > .git $ git statusresults in a file "repo-a/.git/gitdir" that contains
$ cat repo-a/.git/gitdir .git
Quoted 6 lines
I don't see this file mentioned in the gitrepository-layout manpage, and my searches haven't turned up any information on it. What's the purpose of ".git/gitdir"? Are there cases where it will contain something other than ".git"?
Thanks.
It's designed for submodules to work IIUC.
Back in the day each git submodule had its own .git directory keeping its local objects.
Nowadays the repository of submodule <name> is kept in the superprojects .git/modules/<name> directory.
If you are in the submodule however you need to know where the repository is, so we have a file pointing at ../<up until superprojects root dir>/.git/modules/<name> directory.
If not using submodules, I'd expect that file to not be there. If you have a file .git/gitdir which points to plain .git, this is technically correct,
indicating where to find the repository (containing objects etc).
Quoted 8 lines
--
Kyle
git version 2.6.1
--
To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
-----Original Message-----
Quoted 23 lines · Stefan Beller
Quoted 14 lines · Kyle Meyer
When a ".git" file points to another repo, a ".git/gitdir" file is created in that repo.
For example, running
$ mkdir repo-a repo-b $ cd repo-a $ git init $ cd ../repo-b $ echo "gitdir: ../repo-a/.git" > .git $ git statusresults in a file "repo-a/.git/gitdir" that contains
Quoted 7 lines
$ cat repo-a/.git/gitdir .gitI don't see this file mentioned in the gitrepository-layout manpage, and my searches haven't turned up any information on it. What's the purpose of ".git/gitdir"? Are there cases where it will contain something other than ".git"?
Quoted 5 lines
It's designed for submodules to work IIUC.
Back in the day each git submodule had its own .git directory keeping its local >objects.
Nowadays the repository of submodule <name> is kept in the superprojects >.git/modules/<name> directory.
Slightly OT: Is there any way of avoiding having that file in the first place? I'm hoping to have a git repository in a normal file system (Posix) and a working area in a rather less-than-normal one where dots in file names are bad (actually a dot is a separator).
Cheers,
Randall
Quoted 1 line · Randall S. Becker
Slightly OT: Is there any way of avoiding having that file in the first place? I'm hoping to have a git repository in a normal file system (Posix) and a working area in a rather less-than-normal one where dots in file names are bad (actually a dot is a separator).
As said before, I would not expect a file .git/gitdir to be there if not using submodules.
For your OT question, I'd presume you'd have environment variables setup
export GIT_DIR=path_with_no_dots_and_git_repo_in_it # you mention
that is in your posix FS
export GIT_WORK_TREE=/some.place.with.dot.separators
and you'd be good to go.
Quoted 4 lines
Cheers,
Randall
Quoted 12 lines · Kyle Meyer
When a ".git" file points to another repo, a ".git/gitdir" file is created in that repo.
For example, running
$ mkdir repo-a repo-b $ cd repo-a $ git init $ cd ../repo-b $ echo "gitdir: ../repo-a/.git" > .git $ git status
Quoted 4 lines
results in a file "repo-a/.git/gitdir" that contains
$ cat repo-a/.git/gitdir .git
Sounds like a bug in the recently added "worktree" stuff. Perhaps update_linked_gitdir() tweaked by 82fde87f (setup: update the right file in multiple checkouts, 2015-08-25) is misbehaving?
Quoted 14 lines · Junio C Hamano
Quoted 12 lines · Kyle Meyer
When a ".git" file points to another repo, a ".git/gitdir" file is created in that repo.
For example, running
$ mkdir repo-a repo-b $ cd repo-a $ git init $ cd ../repo-b $ echo "gitdir: ../repo-a/.git" > .git $ git status
Quoted 8 lines
Quoted 4 lines
results in a file "repo-a/.git/gitdir" that contains
$ cat repo-a/.git/gitdir .gitSounds like a bug in the recently added "worktree" stuff. Perhaps
update_linked_gitdir()tweaked by82fde87f(setup: update the right file in multiple checkouts, 2015-08-25) is misbehaving?
I noticed that as I was working on the worktree list command that my linked worktree gitdir files were being clobbered to '.git'. I attributed it to my work, but now that you mention it, I think it has happened with the 2.6.1 release as well.
Quoted 20 lines · Mike Rappazzo
Quoted 19 lines · Junio C Hamano
Quoted 16 lines · Kyle Meyer
When a ".git" file points to another repo, a ".git/gitdir" file is created in that repo.
For example, running
$ mkdir repo-a repo-b $ cd repo-a $ git init $ cd ../repo-b $ echo "gitdir: ../repo-a/.git" > .git $ git statusresults in a file "repo-a/.git/gitdir" that contains
$ cat repo-a/.git/gitdir .git
Quoted 8 lines
Quoted 3 lines
Sounds like a bug in the recently added "worktree" stuff. Perhaps
update_linked_gitdir()tweaked by82fde87f(setup: update the right file in multiple checkouts, 2015-08-25) is misbehaving?I noticed that as I was working on the worktree list command that my linked worktree gitdir files were being clobbered to '.git'. I attributed it to my work, but now that you mention it, I think it has happened with the 2.6.1 release as well.
Thanks; I trust those who worked on the worktree feature in 2.6 timeframe would first take a look, OK?
PATCH 1/1 setup: do not create $X/gitdir unnecessarily when accessing git file $X
$X/gitdir is created, or refreshed, in order to keep a linked worktree from being pruned. But while git file is used as the foundation for linked worktrees, it's used for other purposes as well and we should not create $X/gitdir in those cases.
Tighten the check. Only update an existing file, which is an indication this is a linked worktree.
--- setup.c | 2 +- t/t0002-gitfile.sh | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
setup.c +1 -1
@@ -440,7 +440,7 @@ static void update_linked_gitdir(const char *gitfile, const char *gitdir)struct stat st;strbuf_addf (&path,"%s/gitdir" , gitdir); -if (stat (path.buf, &st) || st.st_mtime +24 *3600 <time (NULL )) +if (!stat (path.buf, &st) && st.st_mtime +24 *3600 <time (NULL ))write_file (path.buf,"%s" , gitfile);strbuf_release (&path); }
t/t0002-gitfile.sh +7 -0
@@ -99,6 +99,13 @@ test_expect_success 'check rev-list' ' test "$SHA" = "$(git rev-list HEAD)" ' +test_expect_success '$REAL/gitdir is not created on ordinary git file' ' + echo "gitdir: $REAL" >expected && + test_cmp expected .git && + git status && + ! test -f "$REAL"/gitdir +' + test_expect_success 'setup_git_dir twice in subdir' ' git init sgd && (
Signature · 1 line
2.2.0.513.g477eb31
Re: [PATCH] setup: do not create $X/gitdir unnecessarily when accessing git file $X
Quoted 7 lines · Nguyễn Thái Ngọc Duy
$X/gitdir is created, or refreshed, in order to keep a linked worktree from being pruned. But while git file is used as the foundation for linked worktrees, it's used for other purposes as well and we should not create $X/gitdir in those cases.
Tighten the check. Only update an existing file, which is an indication this is a linked worktree.
Hrm. I think this fixes the immediate problem, but it seems odd for us to rely on "does the file exist"[1].
We trigger this code unconditionally from read_gitfile_gently(). But .git files are a general-purpose mechanism. Shouldn't we be doing this only if we suspect we are working with a linked working tree directory in the first place?
Or we do not know at all, because we are operating in the linked dir, and seeing the presence of the "gitdir" file is the only way we say "ah, it turns out we are linked, so we should take the opportunity to do some maintenance"?
If the latter, then I guess this is the only way to do it. It does seem a bit strange to me that an otherwise read-only operation (reading the file) might involve writing[2].
-Peff
[1] You check only !stat(), so it is not really "does it exist", but "can we stat it". I think that is OK, because this is an opportunistic update, and failing the stat should just mean we don't do the update.
[2] I suspect this code should use write_file_gently(). What happens if I have a read-only linked checkout?
Re: [PATCH] setup: do not create $X/gitdir unnecessarily when accessing git file $X
Quoted 2 lines · Jeff King
[2] I suspect this code should use
write_file_gently(). What happens if I have a read-only linked checkout?
Or you may not be the owner of the repository, you think you are doing a read-only operation, and you silently end up creating a file that cannot be written by the repository owner?
Honestly, I think this whole "just in case the user moved without telling us, we sneakily fix things without telling the user" should just go away. This is not the first incidence of a tool trying to be overly clever and pretend to know better than the end user biting us, is it?
Re: [PATCH] setup: do not create $X/gitdir unnecessarily when accessing git file $X
Quoted 9 lines · Junio C Hamano
Quoted 2 lines · Jeff King
[2] I suspect this code should use
write_file_gently(). What happens if I have a read-only linked checkout?Or you may not be the owner of the repository, you think you are doing a read-only operation, and you silently end up creating a file that cannot be written by the repository owner?
Quoted 5 lines
Honestly, I think this whole "just in case the user moved without telling us, we sneakily fix things without telling the user" should just go away. This is not the first incidence of a tool trying to be overly clever and pretend to know better than the end user biting us, is it?
I have to admit, that was my gut feeling, too, but I do not know enough about the problem it is solving to say whether it is a good tradeoff. Unfortunately 23af91d102e1efaff33b77ab7746356835a3d600 did not have much discussion. I didn't dig into the mailing list, though. I was hoping Duy could summarize it. :)
-Peff
Re: [PATCH] setup: do not create $X/gitdir unnecessarily when accessing git file $X
In reply to Junio C Hamano(resend)
Quoted 4 lines · Junio C Hamano
Quoted 2 lines · Jeff King
[2] I suspect this code should use
write_file_gently(). What happens if I have a read-only linked checkout?
I can't hide anything from you guys can I? :) My first attempt was move this update logic back to setup_..._gentle where it should belong, but it got complicated because read_file_gently was buried too deep and there was no easy way to get the information out.
I can try again, or..
Quoted 10 lines
Or you may not be the owner of the repository, you think you are doing a read-only operation, and you silently end up creating a file that cannot be written by the repository owner?
Honestly, I think this whole "just in case the user moved without telling us, we sneakily fix things without telling the user" should just go away. This is not the first incidence of a tool trying to be overly clever and pretend to know better than the end user biting us, is it?
The whole prune strategy is a bit messy trying to cover all cases while still keeping out of the user's way. Perhaps if we implement "git worktree mv", or even "worktree fixup" so the user can do it manually (back when the prune strategy commit was implemented, there was no git-worktree), then we don't need this magic any more.
So, which way to go?
Signature · 1 line
Duy
Re: [PATCH] setup: do not create $X/gitdir unnecessarily when accessing git file $X
Quoted 7 lines · Duy Nguyen
The whole prune strategy is a bit messy trying to cover all cases while still keeping out of the user's way. Perhaps if we implement "git worktree mv", or even "worktree fixup" so the user can do it manually (back when the prune strategy commit was implemented, there was no git-worktree), then we don't need this magic any more.
So, which way to go?
I'd prefer to see "conservative and minimal first and carefully build up" instead of "snapping something together quickly and having to patch it up in rapid succession before people get hurt." and that is not limited to the "worktree" topic.
I think "if you move, you are on your own, do not do it." would be a good starting point. The user education material would say: if you create worktree B out of the primary A, and if you do not like the location B, you "rm -fr B" and then create a new C out of the primary A at a desired place, and do not reuse location B for any other purpose. The list of worktrees kept somewhere in A would then name the old location B, and it is OK to notice the staleness and remove it, but we do not have to. At that point, the magic can and should go.
After setting the user expectation that way, it is fine to design how we would give "worktree rm" and "worktree mv". As long as users' initial expectation is set to "you do not mv, ever", these can be introduced without hurting their established use pattern that would involve no 'mv'.
PATCH 1/1 worktree: stop supporting moving worktrees manually
The current update_linked_gitdir() has a bug that can create "gitdir" file in non-multi-worktree setup. Instead of fixing this, we step back a bit. The original design was probably not well thought out. For now, if the user manually moves a worktree, they have to fix up "gitdir" file manually or the worktree will get pruned. In future, we probably will add "git worktree mv" to support this use case.
--- Documentation/git-worktree.txt | 6 ++---- setup.c | 12 ------------ 2 files changed, 2 insertions(+), 16 deletions(-)
Documentation/git-worktree.txt +2 -4
@@ -33,10 +33,8 @@ The working tree's administrative files in the repository (see clean up any stale administrative files. If you move a linked working tree to another file system, or -within a file system that does not support hard links, you need to run -at least one git command inside the linked working tree -(e.g. `git status`) in order to update its administrative files in the -repository so that they do not get automatically pruned. +within a file system that does not support hard links, you need to update +$GIT_DIR/worktrees/<id>/gitdir so that they do not get automatically pruned. If a linked working tree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from
setup.c +0 -12
@@ -434,17 +434,6 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)return ret; } -static void update_linked_gitdir (const char *gitfile,const char *gitdir) -{ -struct strbuf path =STRBUF_INIT ; -struct stat st; - -strbuf_addf (&path,"%s/gitdir" , gitdir); -if (stat (path.buf, &st) || st.st_mtime +24 *3600 <time (NULL )) -write_file (path.buf,"%s" , gitfile); -strbuf_release (&path); -} -/* * Try to read the location of the git directory from the .git file, * return path to git directory if found.
@@ -514,7 +503,6 @@ const char *read_gitfile_gently(const char *path, int *return_error_code) error_code =READ_GITFILE_ERR_NOT_A_REPO ; goto cleanup_return; } -update_linked_gitdir (path, dir); path =real_path (dir); cleanup_return:
Signature · 1 line
2.3.0.rc1.137.g477eb31
Re: [PATCH] worktree: stop supporting moving worktrees manually
Quoted 11 lines · Nguyễn Thái Ngọc Duy
The current
update_linked_gitdir()has a bug that can create "gitdir" file in non-multi-worktree setup. Instead of fixing this, we step back a bit. The original design was probably not well thought out. For now, if the user manually moves a worktree, they have to fix up "gitdir" file manually or the worktree will get pruned. In future, we probably will add "git worktree mv" to support this use case.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>---
Documentation/git-worktree.txt The working tree's administrative files in the repository (see · line 34
Quoted 6 lines
Documentation/git-worktree.txt +1
-4@@ -33,10 +33,8 @@ The working tree's administrative files in the repository (see If you move a linked working tree to another file system, or -within a file system that does not support hard links, you need to run -at least one git command inside the linked working tree -(e.g. `git status`) in order to update its administrative files in the -repository so that they do not get automatically pruned. +within a file system that does not support hard links, you need to update
Hmm, is this "hard links" feature implemented? If not, then this documentation is a bit outdated.
Documentation/git-worktree.txt The working tree's administrative files in the repository (see · line 35
Quoted 1 line
Documentation/git-worktree.txt +1
-0+$GIT_DIR/worktrees/<id>/gitdir so that they do not get automatically pruned.
Following the example of af189b4 (Documentation/git-worktree: split technical info from general description, 2015-07-06), it might be a good idea to keep this high-level overview free of such low-level details and instead mention $GIT_DIR/worktrees/<id>/gitdir in the "DETAILS" section.
Perhaps something like this, on top of your patch (assuming that the "hard links" feature is not implemented):
--- 8< ---
Documentation/git-worktree.txt +10 -3
@@ -32,9 +32,9 @@ The working tree's administrative files in the repository (see `git worktree prune` in the main or any linked working tree to clean up any stale administrative files. -If you move a linked working tree to another file system, or -within a file system that does not support hard links, you need to update -$GIT_DIR/worktrees/<id>/gitdir so that they do not get automatically pruned. +If you move a linked working tree, you need to manually update the +administrative files so that they do not get pruned automatically. See +section "DETAILS" for more information. If a linked working tree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from
@@ -135,6 +135,13 @@ thumb is do not make any assumption about whether a path belongs to $GIT_DIR or $GIT_COMMON_DIR when you need to directly access something inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path. +If you move a linked working tree, you need to update the 'gitdir' file +in the entry's directory. For example, if a linked working tree is moved +to `/newpath/test-next` and its `.git` file points to +`/path/main/.git/worktrees/test-next`, then update +`/path/main/.git/worktrees/test-next/gitdir` to reference `/newpath/test-next` +instead. + To prevent a $GIT_DIR/worktrees entry from being pruned (which can be useful in some situations, such as when the entry's working tree is stored on a portable device), add a file named
--- 8< ---
Re: [PATCH] worktree: stop supporting moving worktrees manually
Quoted 8 lines · Eric Sunshine
Quoted 7 lines · Nguyễn Thái Ngọc Duy
The current
update_linked_gitdir()has a bug that can create "gitdir" file in non-multi-worktree setup. Instead of fixing this, we step back a bit. The original design was probably not well thought out. For now, if the user manually moves a worktree, they have to fix up "gitdir" file manually or the worktree will get pruned. In future, we probably will add "git worktree mv" to support this use case.
Quoted 13 lines
Documentation/git-worktree.txt The working tree's administrative files in the repository (see · line 34
Quoted 10 lines
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>---
Documentation/git-worktree.txt +1
-4@@ -33,10 +33,8 @@ The working tree's administrative files in the repository (see If you move a linked working tree to another file system, or -within a file system that does not support hard links, you need to run -at least one git command inside the linked working tree -(e.g. `git status`) in order to update its administrative files in the -repository so that they do not get automatically pruned. +within a file system that does not support hard links, you need to updateHmm, is this "hard links" feature implemented? If not, then this documentation is a bit outdated.
The prune logic is there. But this hard link is not created by 'worktree add'. I think calling link() was done at some point but then it got dropped. Ah found it, it wasn't a big "no" so maybe we can revive it at some point.
http://article.gmane.org/gmane.comp.version-control.git/243475
Quoted 10 lines
Documentation/git-worktree.txt The working tree's administrative files in the repository (see · line 35
Quoted 1 line
Documentation/git-worktree.txt +1
-0+$GIT_DIR/worktrees/<id>/gitdir so that they do not get automatically pruned.Following the example of af189b4 (
Documentation/git-worktree: split technical info from general description, 2015-07-06), it might be a good idea to keep this high-level overview free of such low-level details and instead mention $GIT_DIR/worktrees/<id>/gitdir in the "DETAILS" section.Perhaps something like this, on top of your patch (assuming that the "hard links" feature is not implemented):
Looks good.
How about something like this at the end of the last new paragraph? "alternatively if your file system supports hard link and the worktree and $GIT_DIR are on the same file system, you can create a hard link named "link" back to the .git file. See gitrepository-layout.txt for more information".
Quoted 34 lines
--- 8< ---
Documentation/git-worktree.txt +10
-4@@ -32,9 +32,9 @@ The working tree's administrative files in the repository (see `git worktree prune` in the main or any linked working tree to clean up any stale administrative files. -If you move a linked working tree to another file system, or -within a file system that does not support hard links, you need to update -$GIT_DIR/worktrees/<id>/gitdir so that they do not get automatically pruned. +If you move a linked working tree, you need to manually update the +administrative files so that they do not get pruned automatically. See +section "DETAILS" for more information. If a linked working tree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from@@ -135,6 +135,13 @@ thumb is do not make any assumption about whether a path belongs to $GIT_DIR or $GIT_COMMON_DIR when you need to directly access something inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path. +If you move a linked working tree, you need to update the 'gitdir' file +in the entry's directory. For example, if a linked working tree is moved +to `/newpath/test-next` and its `.git` file points to +`/path/main/.git/worktrees/test-next`, then update +`/path/main/.git/worktrees/test-next/gitdir` to reference `/newpath/test-next` +instead. + To prevent a $GIT_DIR/worktrees entry from being pruned (which can be useful in some situations, such as when the entry's working tree is stored on a portable device), add a file named --- 8< ---
Signature · 1 line
Duy
Re: [PATCH] worktree: stop supporting moving worktrees manually
Quoted 12 lines · Duy Nguyen
Quoted 10 lines · Eric Sunshine
Review
Quoted 6 lines · Nguyễn Thái Ngọc Duy
If you move a linked working tree to another file system, or
(quoted diff) +1
-4-within a file system that does not support hard links, you need to run -at least one git command inside the linked working tree -(e.g. `git status`) in order to update its administrative files in the -repository so that they do not get automatically pruned. +within a file system that does not support hard links, you need to updateHmm, is this "hard links" feature implemented? If not, then this documentation is a bit outdated.
Quoted 6 lines
The prune logic is there. But this hard link is not created by 'worktree add'. I think calling
link()was done at some point but then it got dropped. Ah found it, it wasn't a big "no" so maybe we can revive it at some point.http://article.gmane.org/gmane.comp.version-control.git/243475
Hmm, yes...
Quoted 11 lines
Quoted 10 lines
Quoted 1 line
+$GIT_DIR/worktrees/<id>/gitdir so that they do not get automatically pruned.
Following the example of af189b4 (
Documentation/git-worktree: split technical info from general description, 2015-07-06), it might be a good idea to keep this high-level overview free of such low-level details and instead mention $GIT_DIR/worktrees/<id>/gitdir in the "DETAILS" section.Perhaps something like this, on top of your patch (assuming that the "hard links" feature is not implemented):
Quoted 7 lines
Looks good.
How about something like this at the end of the last new paragraph? "alternatively if your file system supports hard link and the worktree and $GIT_DIR are on the same file system, you can create a hard link named "link" back to the .git file. See gitrepository-layout.txt for more information".
That makes sense, however...
If I understand correctly, while it's true that the 'link' file will inhibit pruning, don't we still have the problem that "git worktree list" will show an outdated path if the user fails to update 'gitdir'? And doesn't the "branch already checked out in some other worktree" interrogation also depend upon 'gitdir' being up-to-date?
Re: [PATCH] setup: do not create $X/gitdir unnecessarily when accessing git file $X
In reply to Nguyễn Thái Ngọc DuyQuoted 12 lines · Nguyễn Thái Ngọc Duy
$X/gitdir is created, or refreshed, in order to keep a linked worktree from being pruned. But while git file is used as the foundation for linked worktrees, it's used for other purposes as well and we should not create $X/gitdir in those cases.
Tighten the check. Only update an existing file, which is an indication this is a linked worktree.
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>---
t/t0002-gitfile.sh test_expect_success 'check rev-list' ' · line 103
Quoted 5 lines
t/t0002-gitfile.sh +5
-0@@ -99,6 +99,13 @@ test_expect_success 'check rev-list' ' +test_expect_success '$REAL/gitdir is not created on ordinary git file' ' + echo "gitdir: $REAL" >expected && + test_cmp expected .git && + git status && + ! test -f "$REAL"/gitdir
Minor: test_path_is_missing() might convey the intention a bit more clearly.
Quoted 1 line
t/t0002-gitfile.sh +1
-0+'