When I do git worktree list
, it display follows.
/path/to/workspace c943d35 [master]
/path/to/workspace ef4df56 (detached HEAD)
It is my working directory (not worktree directory). I do not know how it happened, and how to clean it. I've try git worktree prune
, but it does not change anything. Any help will be appreciated. Many thanks.
git worktree
-- details mentions:
Each linked working tree has a private sub-directory in the repository’s
$GIT_DIR/worktrees
directory.
Check the content of your main repo/.git/worktrees
and see if there is a sub-folder that you could manually remove.
Git 2.20 (Q4 2018) fixes a bug in which the same path could be registered under multiple worktree entries if the path was missing (for instance, was removed manually).
Also, as a convenience, expand the number of cases in which --force
is applicable.
See commit 684e742 (30 Aug 2018) by Jeff King (peff
).
See commit 3a54043, commit f414310, commit 68a6b3a, commit e19831c, commit cb56f55, commit 45059e6, commit 602aaed, commit e5353be, commit 4c5fa9e (28 Aug 2018) by Eric Sunshine (sunshineco
).
(Merged by Junio C Hamano -- gitster
-- in commit 1c515bf, 17 Sep 2018)
worktree
: delete.git/worktrees
if empty after 'remove
'
For cleanliness, "
git worktree prune
" deletes the.git/worktrees
directory if it is empty after pruning is complete.For consistency, make "
git worktree remove <path>
" likewise delete.git/worktrees
if it is empty after the removal.
The same Git 2.20, when traversing objects for reachability and deciding what objects are unreferenced and expendable, have been taught to also consider per-worktree refs of other worktrees as starting points to prevent data loss.
See commit 14f74d5 (03 Nov 2018), commit c9ef0d9, commit b29759d, commit ab3e1f7, commit 061e420, commit 3a3b9d8 (21 Oct 2018), and commit 8aff1a9, commit 5c79f74 (29 Sep 2018) by Nguyễn Thái Ngọc Duy (pclouds
).
See commit a8c754d (21 Oct 2018) by Elijah Newren (newren
).
(Merged by Junio C Hamano -- gitster
-- in commit e146cc9, 13 Nov 2018)
In particular (commit 3a3b9d8):
refs
: new ref types to make per-worktree refs visible to all worktrees
One of the problems with multiple worktree is accessing per-worktree refs of one worktree from another worktree.
This was sort of solved by multiple ref store, where the code can open the ref store of another worktree and has access to the ref space of that worktree.The problem with this is reporting.
"HEAD
" in another ref space is also called "HEAD" like in the current ref space.
In order to differentiate them, all the code must somehow carry the ref store around and print something like "HEAD from this ref store
".Instead of entering a separate ref space, we make refs from other worktrees available in the current ref space.
So "HEAD
" is always HEAD of the current worktree, but then we can have "worktrees/blah/HEAD
" to denote HEAD from a worktree named "blah
".
This syntax coincidentally matches the underlying directory structure which makes implementation a bit easier.The main worktree has to be treated specially because well... it's special from the beginning.
So HEAD from the main worktree is acccessible via the name "main-worktree/HEAD
" instead of "worktrees/main/HEAD
" because "main
" could be just another secondary worktree.This patch also makes it possible to specify refs from one worktree in another one, e.g.
git log worktrees/foo/HEAD
That (the new refs "worktrees/<name>/HEAD
") leads to Git 2.23 (Q2 2019), where the code now sanitizes the names given to worktrees, to make sure these refs are well-formed.
See commit 1de16ae (08 Mar 2019) by Nguyễn Thái Ngọc Duy (pclouds
).
Helped-by: Jeff King (peff
).
(Merged by Junio C Hamano -- gitster
-- in commit 0d107b1, 13 Jun 2019)
worktree add
: sanitize worktree names
Worktree names are based on
$(basename $GIT_WORK_TREE)
.
They aren't significant until 3a3b9d8 (refs
: new ref types to make per-worktree refs visible to all worktrees - 2018-10-21, Git v2.20.0-rc0), where worktree name could be part of a refname and must follow refname rules.Update '
worktree add
' code to remove special characters to follow these rules. In the future the user will be able to specify the worktree name by themselves if they're not happy with this dumb character substitution.
And the same Git 2.22.1 (Q3 2019) mentions "git worktree add
" used to fail when another worktree connected to the same repository was corrupt, which has been corrected.
See commit 105df73 (13 May 2019) by Nguyễn Thái Ngọc Duy (pclouds
).
(Merged by Junio C Hamano -- gitster
-- in commit 933f294, 25 Jul 2019)
worktree add
: be tolerant of corrupt worktrees
find_worktree()
can die() unexpectedly because it usesreal_path()
instead of the gentler version.When it's used in 'git worktree add' (added in cb56f55 (
worktree
: disallow adding same path multiple times, 2018-08-28, Git v2.20.0-rc0), or since v2.20.0. Though the real bug infind_worktree()
is much older) and there's a bad worktree, thisdie()
could prevent people from adding new worktrees.The "bad" condition to trigger this is when a parent of the worktree's location is deleted. Then
real_path()
will complain.Use the other version so that bad worktrees won't affect '
worktree add
'.
The bad ones will eventually be pruned, we just have to tolerate them for a bit.
Before Git 2.26 (Q1 2020), in rare cases "git worktree
add <path>
" could think that <path>
was already a registered worktree even when it wasn't, and refuse to add the new worktree.
This has been corrected.
See commit bb69b3b, commit bb4995f, commit a80c4c2 (24 Feb 2020) by Eric Sunshine (sunshineco
).
(Merged by Junio C Hamano -- gitster
-- in commit 49e5043, 05 Mar 2020)
worktree
: don't allow "add
" validation to be fooled by suffix matchingReported-by: Cameron Gunnin
Signed-off-by: Eric Sunshine
"
git worktree
add <path>
" performs various checks before approving<path>
as a valid location for the new worktree.Aside from ensuring that
<path>
does not already exist, one of the questions it asks is whether<path>
is already a registered worktree.
To perform this check, it queriesfind_worktree()
and disallows the "add
" operation iffind_worktree()
finds a match for<path>
.
As a convenience, however,find_worktree()
casts an overly wide net to allow users to identify worktrees by shorthand in order to keep typing to a minimum.
For instance, it performs suffix matching which, given subtrees "foo/bar
" and "foo/baz
", can correctly select the latter when asked only for "baz
"."
add
" validation knows the exact path it is interrogating, so this sort of heuristic-based matching is, at best, questionable for this use-case and, at worst, may may accidentally interpret<path>
as matching an existing worktree and incorrectly report it as already registered even when it isn't.
(In fact,validate_worktree_add()
already contains a special case to avoid accidentally matching against the main worktree, precisely due to this problem.)Avoid the problem of potential accidental matching against an existing worktree by instead taking advantage of
find_worktree_by_path()
which matches paths deterministically, without applying any sort of magic shorthand matching performed byfind_worktree()
.
And:
worktree
: improvefind_worktree()
documentationSigned-off-by: Eric Sunshine
Do a better job of explaining that
find_worktree()
's main purpose is to locate a worktree based upon input from a user which may be some sort of shorthand for identifying a worktree rather than an actual path.For instance, one shorthand a user can use to identify a worktree is by unique path suffix (i.e. given worktrees at paths "
foo/bar
" and "foo/baz
", the latter can be identified simply as "baz
").
The actual heuristicsfind_worktree()
uses to select a worktree may be expanded in the future (for instance, one day it may allow worktree selection by<id>
of the.git/worktrees/<id>/
administrative directory), thus the documentation does not provide a precise description of how matching is performed, instead leaving it open-ended to allow for future enhancement.While at it, drop mention of the non-NULL requirement of
prefix
sinceNULL
has long been allowed.For instance,
prefix_filename()
has explicitly allowedNULL
since 116fb64e43 (prefix_filename
: drop length parameter, 2017-03-20, Git v2.13.0-rc0), andfind_worktree()
itself since e4da43b1f0(prefix_filename
: return newly allocated string, 2017-03-20, Git v2.13.0-rc0).
Note that the same worktree directory must be registered only once, but "git worktree move
" allowed this invariant to be violated, which has been corrected with Git 2.28 (Q3 2020).
See commit 810382e, commit d179af6, commit 916133e, commit 4a3ce47, commit dd9609a, commit 1b14d40 (10 Jun 2020), and commit c9b77f2 (08 Jun 2020) by Eric Sunshine (sunshineco
).
(Merged by Junio C Hamano -- gitster
-- in commit 9740ef8, 22 Jun 2020)
With Git 2.28 (Q3 2020), The same worktree directory must be registered only once, but "git worktree
move" allowed this invariant to be violated, which has been corrected.
See commit 810382e, commit d179af6, commit 916133e, commit 4a3ce47, commit dd9609a, commit 1b14d40 (10 Jun 2020), and commit c9b77f2 (08 Jun 2020) by Eric Sunshine (sunshineco
).
(Merged by Junio C Hamano -- gitster
-- in commit 9740ef8, 22 Jun 2020)
worktree
: prune duplicate entries referencing same worktree pathSigned-off-by: Eric Sunshine
A fundamental restriction of linked working trees is that there must only ever be a single worktree associated with a particular path, thus "
git worktree add
" explicitly disallows creation of a new worktree at the same location as an existing registered worktree.Nevertheless, users can still "shoot themselves in the foot" by mucking with administrative files in
.git/worktree/<id>/
.Worse, "
git worktree move
" is careless and allows a worktree to be moved atop a registered but missing worktree (which can happen, for instance, if the worktree is on removable media).For instance:
$ git clone foo.git $ cd foo $ git worktree add ../bar $ git worktree add ../baz $ rm -rf ../bar $ git worktree move ../baz ../bar $ git worktree list .../foo beefd00f [master] .../bar beefd00f [bar] .../bar beefd00f [baz]
Help users recover from this form of corruption by teaching "
git worktree prune
" to detect when multiple worktrees are associated with the same path.
And:
worktree
: prune linked worktree referencing main worktree pathReported-by: Jonathan Müller
Signed-off-by: Eric Sunshine
"
git worktree prune
" detects when multiple entries are associated with the same path and prunes the duplicates.However, it does not detect when a linked worktree points at the path of the main worktree.
Although "git worktree add
" disallows creating a new worktree with the same path as the main worktree, such a case can arise outside the control of Git even without the user mucking with.git/worktree/<id>/
administrative files.For instance:
$ git clone foo.git $ git -C foo worktree add ../bar $ rm -rf bar $ mv foo bar $ git -C bar worktree list .../bar deadfeeb [master] .../bar deadfeeb [bar]
Help the user recover from such corruption by extending "
git worktree prune
" to also detect when a linked worktree is associated with the path of the main worktree.
Note that Git 2.30 does list locked worktrees:
See commit c57b336:
worktree: teach
list
to annotate locked worktree
The "
git worktree list
" shows the absolute path to the working tree, the commit that is checked out and the name of the branch. It is not immediately obvious which of the worktrees, if any, are locked."git worktree remove" refuses to remove a locked worktree with an error message. If "
git worktree list
" told which worktrees are locked in its output, the user would not even attempt to remove such a worktree, or would realize that "git worktree remove -f -f <path>
" is required.Teach "
git worktree list
" to append "locked
" to its output.
The output from the command becomes like so:$ git worktree list /path/to/main abc123 [master] /path/to/worktree 456def (detached HEAD) /path/to/locked-worktree 123abc (detached HEAD) locked
With Git 2.33 (Q3 2021), "git worktree add --lock
"(man) learned to record why the worktree is locked with a custom message.
See commit 0db4961 (15 Jul 2021), and commit f7c35ea, commit f9365c0 (11 Jul 2021) by Stephen Manz (SRManz
).
(Merged by Junio C Hamano -- gitster
-- in commit 01369fd, 28 Jul 2021)
worktree
: teachadd
to accept--reason <string>
with--lock
Signed-off-by: Stephen Manz
Reviewed-by: Eric Sunshine
The default reason stored in the lock file, "
added with --lock
", is unlikely to be what the user would have given in a separategit worktree lock
(man) command.
Allowing--reason
to be specified along with--lock
when adding a working tree gives the user control over the reason for locking without needing a second command.
git worktree
now includes in its man page:
git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]] [-b <new-branch>] <path> [<commit-ish>]
git worktree
now includes in its man page:
With
lock
or withadd --lock
, an explanation why the working tree is locked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With