Skip to content

Instantly share code, notes, and snippets.

@jonathanduke
Last active November 16, 2024 17:05
Show Gist options
  • Select an option

  • Save jonathanduke/92eac20fe8a85eff8e8840b5d56551f9 to your computer and use it in GitHub Desktop.

Select an option

Save jonathanduke/92eac20fe8a85eff8e8840b5d56551f9 to your computer and use it in GitHub Desktop.
List all Git worktrees recursively with the location of the repository (either a .git directory or the gitdir location specified in the .git file)
::::
:: Original source: https://gist.github.com/jonathanduke/92eac20fe8a85eff8e8840b5d56551f9#file-git-list-worktrees-bat
:: Public domain: http://unlicense.org/
:: Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
::::
@echo off
setlocal EnableDelayedExpansion
for /f "tokens=*" %%f in ('dir /a /s /b .git') do (
if exist "%%f\*" (
set "_dir=%%~dpf"
set "_tgt=%%f"
echo D !_dir:~0,-1! !_tgt:\=/!
) else (
set "_dir=%%~dpf"
set /p _tgt=<"%%f"
echo F !_dir:~0,-1! !_tgt:gitdir: =!
)
)
::::
:: Original source: https://gist.github.com/jonathanduke/92eac20fe8a85eff8e8840b5d56551f9#file-git-set-worktrees-bat
:: Public domain: http://unlicense.org/
:: Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
::::
@echo off
setlocal EnableDelayedExpansion
for /f "tokens=1,2,3 delims= " %%a in (git-worktrees.txt) do (
if "%%a" == "F" (
set "_=%%b"
set "_=!_:\=/!"
echo %%b\.git
echo gitdir: %%c
attrib -h "%%b\.git" > nul
if exist "%%b\.git\*" (
git --git-dir="!_!/.git" --work-tree="!_!" config core.worktree "!_!"
ren "%%b\.git" %%~nxc
echo gitdir: %%~nxc> "%%b\.git"
) else (
git --git-dir="%%c" --work-tree="!_!" config core.worktree "!_!"
echo gitdir: %%c> "%%b\.git"
)
attrib +h "%%b\.git"
)
)
@jonathanduke
Copy link
Author

If a folder contains a .git directory, the line will start with a D and the third column will contain its full path. However, if a folder contains a .git file, the line will start with an F and the third column will contain the path listed in the file (which could be relative to the worktree folder).

For example:

D	C:\Code\Personal\Example1	C:/Code/Personal/Example1/.git
F	C:\Code\Business\Example2	D:/.repos/github.com/myworkplace/example2.git

In this case, the main worktree at C:\Code\Personal\Example1 would contain a standard .git folder, but the linked worktree at C:\Code\Business\Example2 would instead contain a .git file like this:

gitdir: D:/.repos/github.com/myworkplace/example2.git

If the main worktree is detached and linked from a different folder, then the repository should be configured in D:/.repos/github.com/myworkplace/example2.git/config to point back to the worktree:

[core]
	worktree = C:\Code\Business\Example2

Note that it is possible for a single repository to have multiple worktrees:

D	C:\Code\Personal\Example1	C:/Code/Personal/Example1/.git
F	C:\Code\Personal\hotfix3	C:/Code/Personal/Example1/.git/worktrees/hotfix3

@jonathanduke
Copy link
Author

You can use git-set-worktrees.bat to process the output of git-list-worktrees.bat (expected to be git-worktrees.txt) to create .git pointer files and set the worktree paths so that the .git folder and your actual workspace files can be located on separate drives or folders. This will modify your repositories, so don't run it on a whole batch of them until you test it and understand what it's doing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment