Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Find all Git Bare and non-Bare repository?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#!/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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading