Rob Bednark
Rob Bednark

Reputation: 28192

How to show only untracked sub-repos (not files) in git?

How do I show only untracked subdirectories that are git repos? Do I use git diff, git status, or git ls? What options do I use?

The closest thing I could find is:
git diff --name-only --diff-filter=M
but that shows modified, not untracked. And it shows files.

I'm looking for something like:

$ git init .
Initialized empty Git repository in /tmp/my-dir
$ touch my-file
$ git add my-file
$ git commit -m 'init'
[master (root-commit) 3f18576] init
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 my-file
$ echo changed >> my-file
$ mkdir sub-repo
$ cd sub-repo
$ git init .
Initialized empty Git repository in /tmp/my-dir/sub-repo/.git/
$ touch my-file-sub-repo
$ cd ..
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   my-file

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    sub-repo/

$ git # diff? What options?
my-dir

(Related: I don't know how git is treating these "sub-repos" but would like to understand. Maybe git is considering them as git submodules, even though I never explicitly ran any git submodule commands?)

Upvotes: 0

Views: 94

Answers (1)

jthill
jthill

Reputation: 60383

hmm. Okay, from the rewrite it seems what you want is the nested work trees or repositories that aren't tracked?

(
echo .git
git ls-files -s | sed -n '/^16/s,[^\t]*.,,p'
find -mindepth 1 -type d \( \
    \( -exec test -d {}/objects -a -d {}/refs -a -f {}/HEAD \; -prune -printf %P\\n \) \
 -o \( -exec test -e {}/.git \; -prune -printf %P\\n \) \)
) | sort | uniq -u

====

but the original question, showing all directories containing no tracked files, is also interesting, so here's what I had for that:

Git's flexible, arguably (though I'd disagree strongly) flexible to a fault, about where repositories and their work trees can reside, to the point where it's possible for a trolling guru to make it impossible to tell, but if we rule out such hopefully-playful malice it's down in fiveliner range.

All directories that contain files tracked in the current checkout anywhere underneath:

git ls-files \*/* \
| awk '{while(sub(/\/[^/]*$/,""))if(!seen[$0]++)print;else break}'

All directories that could contain tracked files:

find -mindepth 1 -type d \( \
      \( -exec test -d {}/objects -a -d {}/refs -a -f {}/HEAD \; -prune \) \
   -o \( -exec test -e {}/.git \; -prune -printf %P\\n \) \
   -o -printf %P\\n \)

And then just look for un-duplicated entries:

( git ls-files \*/* \
  | awk '{while(sub(/\/[^/]*$/,""))if(!seen[$0]++)print;else break}'

  find -mindepth 1 -type d \( \
      \( -exec test -d {}/objects -a -d {}/refs -a -f {}/HEAD \; -prune \) \
   -o \( -exec test -e {}/.git \; -prune -printf %P\\n \) \
   -o -printf %P\\n \)
) | sort | uniq -u

====

Upvotes: 1

Related Questions