I want to loop over all the directories and find out all the git repositories (both Bare and non-Bare). However, I need to identify which one is Bare and which one is non-Bare so that I can run different operations on them.
I checked Check if current directory is a Git repository and How do I check if a repository is bare?.
The script I came up with is:
#!/bin/bash
for d in $(find /media/ismail/8TBRaid0/ABC -path '*/.git*' -prune -o -print -type d); do
if git --git-dir=$d rev-parse --is-inside-work-tree > /dev/null 2>&1; then
echo ${d} is a non-Bare Repository
elif git --git-dir=$d rev-parse --is-bare-repository > /dev/null 2>&1; then
echo ${d} is a is a Bare Repository
fi
done
The output I am getting is:
/media/ismail/8TBRaid0/ABC/d is a non-Bare Repository
/media/ismail/8TBRaid0/ABC/e is a non-Bare Repository
The problem is:
ABC has 5 directories.
ABC% ls -la
total 28
drwxrwxr-x 7 ismail ismail 4096 Jun 9 16:44 .
drwxr--r-- 16 ismail ismail 4096 Jun 9 16:44 ..
drwxrwxr-x 3 ismail ismail 4096 Jun 9 16:44 a
drwxrwxr-x 3 ismail ismail 4096 Jun 9 16:44 b
drwxrwxr-x 3 ismail ismail 4096 Jun 9 16:44 c
drwxrwxr-x 7 ismail ismail 4096 Jun 9 16:44 d
drwxrwxr-x 7 ismail ismail 4096 Jun 9 16:44 e
Here a,b,c are non-Bare Repositories with .git directory. And d,e are Bare Repositories without .git directory.
So, the output I am getting is definitely wrong. What i need for my case is:
a is a non-Bare Repository
b is a non-Bare Repository
c is a non-Bare Repository
d is a Bare Repository
e is a Bare Repository
How can I get the expected result?
Update 1:
My directory structure is actually deeper and scattered. The structure I gave above is as an example. For example: the structure can be:
.
βββ 1
βΒ Β βββ a
βββ 2
βΒ Β βββ 3
βΒ Β βββ b
βΒ Β βββ e
βΒ Β βββ branches
βΒ Β βββ config
βΒ Β βββ description
βΒ Β βββ HEAD
βΒ Β βββ hooks
βΒ Β βΒ Β βββ applypatch-msg.sample
βΒ Β βΒ Β βββ commit-msg.sample
βΒ Β βΒ Β βββ fsmonitor-watchman.sample
βΒ Β βΒ Β βββ post-update.sample
βΒ Β βΒ Β βββ pre-applypatch.sample
βΒ Β βΒ Β βββ pre-commit.sample
βΒ Β βΒ Β βββ pre-merge-commit.sample
βΒ Β βΒ Β βββ prepare-commit-msg.sample
βΒ Β βΒ Β βββ pre-push.sample
βΒ Β βΒ Β βββ pre-rebase.sample
βΒ Β βΒ Β βββ pre-receive.sample
βΒ Β βΒ Β βββ update.sample
βΒ Β βββ info
βΒ Β βΒ Β βββ exclude
βΒ Β βββ objects
βΒ Β βΒ Β βββ info
βΒ Β βΒ Β βββ pack
βΒ Β βββ refs
βΒ Β βββ heads
βΒ Β βββ tags
βββ c
βββ d
βΒ Β βββ branches
βΒ Β βββ config
βΒ Β βββ description
βΒ Β βββ HEAD
βΒ Β βββ hooks
βΒ Β βΒ Β βββ applypatch-msg.sample
βΒ Β βΒ Β βββ commit-msg.sample
βΒ Β βΒ Β βββ fsmonitor-watchman.sample
βΒ Β βΒ Β βββ post-update.sample
βΒ Β βΒ Β βββ pre-applypatch.sample
βΒ Β βΒ Β βββ pre-commit.sample
βΒ Β βΒ Β βββ pre-merge-commit.sample
βΒ Β βΒ Β βββ prepare-commit-msg.sample
βΒ Β βΒ Β βββ pre-push.sample
βΒ Β βΒ Β βββ pre-rebase.sample
βΒ Β βΒ Β βββ pre-receive.sample
βΒ Β βΒ Β βββ update.sample
βΒ Β βββ info
βΒ Β βΒ Β βββ exclude
βΒ Β βββ objects
βΒ Β βΒ Β βββ info
βΒ Β βΒ Β βββ pack
βΒ Β βββ refs
βΒ Β βββ heads
βΒ Β βββ tags
βββ f
βββ ADOC Document.adoc
>Solution :
For starters, look at the output of your find command:
$ find ABC -path '*/.git*' -prune -o -print -type d
ABC
ABC/a
ABC/b
ABC/c
ABC/d
ABC/d/branches
ABC/d/hooks
ABC/d/hooks/applypatch-msg.sample
ABC/d/hooks/commit-msg.sample
ABC/d/hooks/post-update.sample
[...]
That’s not really useful at all. If everything contained in .../ABC is a git repository, you can just get a list of directories:
$ find ABC/* -maxdepth 0 -type d
ABC/a
ABC/b
ABC/c
ABC/d
ABC/e
That’s going to be much easier to work with. We can then iterate over those results like this:
find ABC/* -maxdepth 0 -type d |
while read dir; do
# note that --is-bare-repository returns results as a string
# not an exit code
is_bare=$(git -C $dir rev-parse --is-bare-repository 2> /dev/null)
if [ "$is_bare" = true ]; then
echo "$dir is a bare repository"
else
echo "$dir is not a bare repository"
fi
done
Running that code produces:
ABC/a is not a bare repository
ABC/b is not a bare repository
ABC/c is not a bare repository
ABC/d is a bare repository
ABC/e is a bare repository
If some things in ABC may not be git repositories, we can add an
additional clause inside the while loop:
...
is_bare=$(git -C $dir rev-parse --is-bare-repository 2> /dev/null)
if [ $? -ne 0 ]; then
echo "$dir is not a git repository"
continue
fi
...
Update
If your directory structure is more varied, we can find git repositories by looking for a file named HEAD:
$ find ABC -name HEAD -printf "%h\n"
ABC/c/.git
ABC/1/a/.git
ABC/1/d
ABC/2/b/.git
ABC/2/e
That means we can rewrite the script to look like:
find ABC -name HEAD -printf "%h\n" |
while read dir; do
if [[ $dir =~ /\.git/ ]]; then
dir=${dir%/.*}
fi
# note that --is-bare-repository returns results as a string
# not an exit code
is_bare=$(git -C "$dir" rev-parse --is-bare-repository 2> /dev/null)
if [[ $is_bare = true ]]; then
echo "$dir is a bare repository"
else
echo "$dir is not a bare repository"
fi
done
Note that I’m using some bash-specific syntax here to make our lives easier, but that shouldn’t be a problem in most environments.
Given this directory tree:
ABC/
βββ 1
βΒ Β βββ a # non-bare repository
βΒ Β βββ d # bare repository
βββ 2
βΒ Β βββ b # non-bare repository
βΒ Β βββ e # bare repository
βββ c # non-bare repository
βββ z # not a repository
The script above produces:
ABC/c is not a bare repository
ABC/1/a is not a bare repository
ABC/1/d is a bare repository
ABC/2/b is not a bare repository
ABC/2/e is a bare repository