查找所有 Git Bare 和非 Bare 存储库?

问题描述 投票:0回答:3

我想遍历所有目录并找出所有 git 存储库(裸露和非裸露)。但是,我需要确定哪一个是 Bare,哪一个是非 Bare,以便我可以对它们运行不同的操作。

我检查了 检查当前目录是否是 Git 存储库如何检查存储库是否是裸露的?.

我想出的脚本是:

#!/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

我得到的输出是:

/media/ismail/8TBRaid0/ABC/d is a non-Bare Repository
/media/ismail/8TBRaid0/ABC/e is a non-Bare Repository

问题是:

ABC 有 5 个目录。

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

这里 a、b、c 是带有 .git 目录的非裸存储库。 d、e 是没有 .git 目录的裸存储库。

所以,我得到的输出肯定是错误的。我的案例需要的是:

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

怎样才能得到预期的结果?

更新1:

我的目录结构实际上更深、更分散。我上面给出的结构只是一个例子。例如:结构可以是:

.
├── 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
bash git
3个回答
2
投票

对于初学者,请查看

find
命令的输出:

$ 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
[...]

这根本没有什么用处。如果

.../ABC
中包含的所有内容都是 git 存储库,您只需获取目录列表即可:

$ find ABC/* -maxdepth 0 -type d
ABC/a
ABC/b
ABC/c
ABC/d
ABC/e

这将更容易使用。然后我们可以像这样迭代这些结果:

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

运行该代码会产生:

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

如果

ABC
中的某些内容可能不是
git
存储库,我们可以添加一个
while
循环内的附加子句:

  ...
  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
  ...

更新

如果您的目录结构更加多样化,我们可以通过查找名为

HEAD
:

的文件来找到 git 存储库
$ find ABC -name HEAD -printf "%h\n"
ABC/c/.git
ABC/1/a/.git
ABC/1/d
ABC/2/b/.git
ABC/2/e

这意味着我们可以将脚本重写为:

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

请注意,我在这里使用了一些特定于 bash 的语法,以使我们的生活更轻松,但这在大多数环境中不应该成为问题。

给定这个目录树:

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

上面的脚本产生:

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

1
投票

你也许可以用一些

find+bash
机械来完成这一切:

$ cat myScript
#!/usr/bin/env bash

iiwt() {
  [[ $(git -C "$1" rev-parse --is-inside-work-tree 2> /dev/null) == "true" ]] &&
  echo "$1 is a non-Bare Repository"
}

ibr() {
  [[ $(git -C "$1" rev-parse --is-bare-repository 2> /dev/null) == "true" ]] &&
  echo "$1 is a Bare Repository"
}

export -f iiwt ibr

find . -type d -exec bash -c 'iiwt "$1" || ibr "$1"' _ {} \; -prune

说明:

  • iiwt
    辅助函数测试其参数是否位于工作树内。如果是,它会打印一条消息,并且其退出状态为 true。否则其退出状态为 false。

  • ibr
    辅助函数测试其参数是否位于裸存储库中。如果是,它会打印一条消息,并且其退出状态为 true。否则其退出状态为 false。

  • find 命令搜索所有目录并在每个目录上执行 bash 脚本

    iiwt "$1" || ibr "$1"
    。如果退出状态为 true find 会在此处停止递归(这就是
    -prune
    的用途)。否则它会在内部递归。

演示:

$ mkdir -p foobar/bar foobar/a/b/c; cd foobar
$ git init --bare foo.git
$ git clone foo.git
$ git init --bare bar/foo.git
$ git clone bar/foo.git bar/foo
$ find . -type d
.
./a
./a/b
./a/b/c
./foo.git
./foo.git/refs
./foo.git/refs/heads
...
./foo/.git/refs/heads
./foo/.git/refs/tags
./foo/.git/branches
$ myScript .
./foo is a non-Bare Repository
./foo.git is a Bare Repository
./bar/foo.git is a Bare Repository
./bar/foo is a non-Bare Repository

请注意,我们也可以使用一个辅助函数:

$ cat myScript
#!/usr/bin/env bash

hlp() {
  if [[ $(git -C "$1" rev-parse --is-inside-work-tree 2> /dev/null) == "true" ]]; then
    echo "$1 is a non-Bare Repository"
  elif [[ $(git -C "$1" rev-parse --is-bare-repository 2> /dev/null) == "true" ]]; then
    echo "$1 is a Bare Repository"
  else
    return 1
  fi
}

export -f hlp

find . -type d -exec bash -c 'hlp "$1"' _ {} \; -prune

0
投票

OP在这里。

我发布这个答案的原因是,我想添加更多信息。

--is-inside-git-dir
对于裸露和常规 git 存储库都返回 true。
--is-bare-repository
仅对于裸存储库返回 true。

因此,我使用的代码是:

find . -name HEAD -type f -execdir test -d refs -a -d objects \; -printf "%h\n" | while read ORIGINAL_REPO_LOCATION; do
    is_bare=$(git -C "$ORIGINAL_REPO_LOCATION" rev-parse --is-bare-repository 2> /dev/null)

    is_git_repo=$(git -C "$ORIGINAL_REPO_LOCATION" rev-parse --is-inside-git-dir 2> /dev/null)

    if [[ "$is_bare" == "true" ]]; then
        echo "$ORIGINAL_REPO_LOCATION is a bare git repo"
    elif [[ "$is_git_repo" == "true" ]]; then
        echo "$(dirname "$ORIGINAL_REPO_LOCATION") is a git repo"
    else
        echo "$ORIGINAL_REPO_LOCATION is not a git repo"
    fi
done
© www.soinside.com 2019 - 2024. All rights reserved.