管理许多git存储库

时间:2009-05-03 09:01:15

标签: git multiple-repositories

在git中设置项目很简单,所以即使是小脚本我也可以拥有单独的存储库。现在的问题是如何管理它们。

我使用这些存储库在多个地方工作。当我对某个存储库进行了更改时,我希望能够在其他位置更新存储库。

所以我有一个包含许多存储库的目录。

  1. 我如何获取所有这些?
  2. 如何检查其中是否有任何未提交的更改?
  3. 如何检查是否有任何更改要合并?
  4. 能用一个命令完成这些操作会很高兴。

    输出需要足够沉默才能真正注意到要做的事情。

23 个答案:

答案 0 :(得分:40)

我强烈推荐多个存储库工具mr。我曾经使用其他人推荐的自定义shell脚本一段时间,但使用mr对我有以下好处:

  • 它是通用的:可以使用各种版本控制系统的结合,不仅仅是git(例如Mercurial,SVN等)。
  • 速度很快:先生可以并行执行多个作业。我使用了一些git / mercurial存储库,并且每天都会多次同步它们。先生极大地加快了这个过程。
  • 管理存储库检出列表简单快捷。只需使用'mr register'而不是修改自定义脚本中的项目列表。

关于静默输出的问题:可以使用命令行开关-q修改详细程度。我更喜欢默认输出,它看起来很简单地将输出统一起来。

我使用mr命令的以下别名来确保mr始终选择存储在$ HOME中的默认项目列表,并使用5个并行线程:

alias mr='mr -d ~/ -j 5 '

答案 1 :(得分:14)

我必须说我从目前接受的答案开始(只是一堆辅助脚本遍历存储库),但总而言之,这对我来说是一种缺乏经验。

所以,在尝试了mr,repo和git-submodules之后,我发现每个都缺少不同的方式,所以,我最终做了我自己的变体:http://fabioz.github.io/mu-repo这是一个成熟的工具 - 在这一点上 - 它有工作流程,允许您:

  • 克隆多个回购
  • diff(并编辑)多个repos中的当前更改
  • 预览传入的更改
  • 在多个repos中并行运行命令
  • 创建回购组
  • 在多个repos上运行与git相关的命令
  • 等(有关详情,请参阅homepage)。

请注意,它支持Python运行的任何操作系统;)

答案 2 :(得分:11)

gr(git-run)扩展了mr的功能(仅适用于git)。我发现使用其标签系统组织多个git repos更容易。但gr的代码并未得到很好的维护。如果您使用的是bash,请务必使用-t tag代替#tag表单。

答案 3 :(得分:7)

您可以尝试将repo与自定义manifest.xml文件一起使用,以指定存储库的位置。关于如何执行此操作有some documentation

或者您可以使用git-submodule(1)

答案 4 :(得分:4)

gitslave是一个工具,它可以通过在super和subs之间创建超级项目/子项目关系,在许多存储库上运行相同的命令。这(默认情况下)提供输出摘要,因此您可以专注于提供唯一输出的存储库(对于git状态很有用,对git ls-files不太有用)。

这通常用于需要将多个存储库组合在一起并同时将它们保存在同一分支或标记上的项目。对于我的(裸)存储库目录,我只有一个makefile,它允许我运行任意git命令,如你所见,我主要用于fsck和gc:

full: fsck-full gc-aggressive
        @:

fsck-full:
        for f in */.; do (cd $$f; echo $$f; git fsck --full || echo $$f FAILED); done

gc-aggressive:
        for f in */.; do (cd $$f; echo $$f; git gc --aggressive || echo $$f FAILED); done

%:
        for f in */.; do (cd $$f; git $@ || echo $$f FAILED); done

答案 5 :(得分:3)

我使用这个脚本在我的所有存储库中轻松执行git命令。

#!/bin/sh
if [ ! "$1" = "" ] ; then

   if [ "$GITREPO" = "" -a -d "$HOME/cm/src" ] ; then
      GITREPO="$HOME/cm/src"
   fi

   if [ "$GITREPO" != "" ] ; then

      echo "Git repositories found in $GITREPO"
      echo "-=-=-=-=-=-=-=-=-=-=-=-=-=-"

      DIRS="`/bin/ls -1 $GITREPO`"

      for dir in $DIRS ; do

         if [ -d $GITREPO/$dir/.git ] ; then
            echo "$dir -> git $1"
            cd $GITREPO/$dir ; git $@
            echo
         fi

      done
   else

      echo "Git repositories not found."

   fi
fi

默认情况下,脚本会在〜/ cm / src中查找git存储库,但您可以通过根据自己的喜好设置GITREPO环境变量来覆盖它。

此脚本基于this script

答案 6 :(得分:3)

您可以使用git-status-all gem:https://github.com/reednj/git-status-all

# install the gem    
gem install git-status-all

# use the status-all subcommand to scan the directory
git status-all

还有一个提取选项,可以在显示状​​态之前从所有存储库的原点获取:

git status-all --fetch

git status all

答案 7 :(得分:3)

我编写了一个名为“ RepoZ”的工具,该工具会在您克隆或更改其中的任何内容(例如切换分支)后立即自动发现git存储库。

找到后,将对存储库进行“跟踪”。这只会在本地存储库列表中显示它们,包括受posh-git启发的密集状态信息。其中包含当前分支以及其他内容,例如文件编辑以及传入或传出提交的数量。

RepoZ UI

这有助于跟踪您的本地存储库以及未完成的要提交或推送的工作。此外,您可以使用存储库列表作为导航从一个存储库切换到另一个存储库。

RepoZ Navigation

“如何获取所有这些?”

用于Windows的版本提供了一个上下文菜单来提取或提取存储库。通过多选,您可以一次在多个存储库上运行操作。

但是,您可能会发现另一个非常有用的功能:

RepoZ Auto-Fetch

使用自动获取,您可以告诉RepoZ定期在后台获取所有git存储库的远程目录。当然,这些提取不会与您的本地提交冲突。没有像git pull这样的本地合并尝试。

答案 8 :(得分:1)

为此,您可以使用 every,它可以按照此模式在多个目录中运行 cli 命令 every <command>

安装: npm i -g every-cli

用法示例: every git branch

- repo-1
  master
- repo-2
  develop

答案 9 :(得分:1)

如果还有人在看这个帖子,请查看我的shell脚本gitme

您需要手动输入本地git repos,但我每天都使用此工具在多台计算机上协作多个git项目。

您可以运行git clone https://github.com/robbenz/gitme.git

脚本也发布在

下面
#!/bin/bash -e

REPOS=( 
/Users/you/gitrepo1
/Users/you/gitrepo2
/Users/you/gitrepo3
/Users/you/gitrepo4
)

MOVE="Moving to next REPO... \n" 

tput setaf 2;echo "What ya wanna do? You can say push, pull, commit, ftp push, or status"; tput sgr0

read input

if [ $input =  "commit" ]
then
    tput setaf 2;echo "Do you want a unique commit message? [y/n]";tput sgr0
    read ans
    if [ $ans = "y" ]
    then 
        for i in "${REPOS[@]}"
        do
            cd "$i"
            tput setaf 6;pwd;tput sgr0 
            git add . -A
            read -p "Commit description: " desc  
            git commit -m "$desc"
            tput setaf 2;echo  $MOVE;tput sgr0 
            sleep 1
        done 
    else 
        for i in "${REPOS[@]}"
        do
            cd "$i"
            tput setaf 6;pwd;tput sgr0 
            git add . -A
            git commit -m "autocommit backup point"
            tput setaf 2;echo  $MOVE;tput sgr0 
            sleep 1
        done
    fi 
elif [ $input = "push" ] || [ $input = "pull" ] || [ $input = "ftp push" ] || [ $input = "status" ]
    then
        for i in "${REPOS[@]}"
do
    cd "$i"
    tput setaf 6;pwd;tput sgr0 
    git $input 
    tput setaf 2;echo  $MOVE;tput sgr0 
    sleep 1
    done 
else tput setaf 1;echo "You have zero friends";tput sgr0 
fi

我在〜/ .bash_profile中设置了一个别名alias gitme='sh /path/to/gitme.sh'

答案 10 :(得分:1)

我刚刚创建了一个可以满足您需求的工具!

  1. 我如何获取所有这些? gmaster fetch
  2. 如何检查其中是否有任何未提交的更改? gmaster status
  3. 如何检查是否有任何更改要合并? gmaster status
  4. 它被称为gitmaster:https://github.com/francoiscabrol/gitmaster

答案 11 :(得分:1)

我将这个简单的bash函数编写到我的.bash_profile中,只能在所有git存储库中运行git,maven,gradle或任何其他bash命令:

# usefull function to work with multiple git repositories
all() {
    failed=0
    printf '>>> START RUNNING: "%s" >>>' "$*"
    for d in */; do
        pushd "$d" > /dev/null
        if [ -d ".git" ]
        then
            printf '\n--------------------------------------------\n\n'
            pwd
            eval $@
            if [ $? -ne 0 ]
            then
                failed=1
                break;
            fi
        fi
        popd > /dev/null
    done
    if [ $failed -eq 0 ]
    then
        printf '\n--------------------------------------------\n'
        printf '<<< RAN "%s" WITH SUCCESS!!! <<<' "$*"
    else
        printf '\n<<< FAILED!!! <<<'
    fi
}

这可以这样使用

all git st
all git pull
all ./gradlew clean test
etc.

答案 12 :(得分:1)

我已经做了一个别名和一个函数,以在目录中可用的所有存储库上(递归地)运行任何git命令。您可以在这里找到它:https://github.com/jaguililla/dotfiles/git

这是代码:

#!/bin/sh
# To use it: source git_aliases

# Example: rgita remote \;
alias rgita='find . -type d -name .git -execdir git'

# Example: rgit remote -vv
rgit() {
  rgita "$@" \;
}

希望它会有所帮助:)

答案 13 :(得分:0)

我使用代码编辑器(VS代码)的多光标选择/多行编辑功能来创建批处理/ shell脚本并一次性执行。通过这个简单的愚蠢的解决方案,我知道我在做什么,并且可以从执行这些命令中得到什么。无需猜测,无需学习,无需定制。另一个原因是,每次我想对驻留在公共父目录中的不同存储库集上的命令执行时。

答案 14 :(得分:0)

请按照以下步骤从所有代码库中提取代码:

  1. 使用 .bat 扩展名创建一个新文件
  2. 将该文件放在您拥有所有存储库文件夹的同一层次结构中
  3. 编辑 .bat 文件并添加下面提到的脚本
FOR /D %%G in (%cd%\*) Do cd %%G & call git branch & call git pull & cd ..
echo All code pulled successfully!!
pause
  1. 保存文件并双击以开始提取代码

答案 15 :(得分:0)

我发现了一个很好的解决方案,即使每个仓库都签出了不同的分支,也可以从所有具有.git文件夹的子目录中从当前分支中提取信息。 该命令是一种单行代码,足够灵活,可以针对不同的git命令进行修改,并且可以使用别名。

只需复制并粘贴以下内容:

find . -type d -maxdepth 2 -name .git -exec sh -c 'cd $0 && cd .. && git pull origin $(git rev-parse --abbrev-ref HEAD)' {} \;

打破现状:

find . -type d -maxdepth 2 -name .git 

查找当前目录(查找。)中所有名称为“ .git”(-name .git)的目录(-d),最多查找两个目录(2个而不是1个,因为我们是在git repo文件夹中查找git文件夹。

-exec sh -c 

运行以下shell命令(exec sh -c)

'cd $0 && cd .. && git pull origin $(git rev-parse --abbrev-ref HEAD)'

将目录更改为第一个参数(cd $ 0),然后向上一级更改目录以保留.git文件夹(cd ..),然后执行git pull origin,同时通过运行git rev-parse ...指定分支当前分支的HEAD提交。

{} \;

“ {}”是我们从初始 find 命令获得的结果相对路径。的;用于结束命令。

在zsh的MacOS 10.14.6上测试。按原样,仅当远程分支机构和本地分支机构被命名为AFAIK时才起作用。

您可以修改它以获取状态。我希望您可以添加参数以进一步提高灵活性,但是我还没有尝试过。

答案 16 :(得分:0)

我使用Visual Studio代码。我们的代码库中大约有20个库,它们都是单独的Git存储库,而Visual Studio Code中的源代码控制选项卡非常适合查看本地存储库落后或超前的情况。还有一些设置可以定期获取以使该信息保持最新状态,还有刷新按钮。

它不像脚本那样方便,但是对我来说,当涉及到源代码控制时,我喜欢成为进行更改的人。要精心编写脚本,要小心不要覆盖更改等。使用VS Code方法,您可以快速获得大量信息,可以自己采取行动。

这是它的屏幕截图:

Source control window in VS Code

答案 17 :(得分:0)

有一个方便的工具可以提取所有多个存储库。 git-pull-all是一个命令行工具,可在多个git存储库中异步执行。

安装

npm install -g git-pull-all

用法

假设您具有以下文件和目录:

~/Projects/
  cool-examples/
    .git/
  funny-movies/
  my-todos.txt
  super-express/
    .git/

git-pull-all目录上运行~/Projects命令时,它应该找到子git存储库(在上述情况下为 cool-examples super-express ),然后对它们分别执行git pull

$ cd ~/Projects
$ git-pull-all
funny-movies/
Not a git repository
cool-examples/
Already up-to-date.
super-express/
Already up-to-date.
Done!
git-pull-all ~/Projects

GitHub链接:https://github.com/tatsuyaoiw/git-pull-all

答案 18 :(得分:0)

免责声明:我正在www.repoflow.com上使用此工具

  

如何获取所有这些内容?
  如何检查其中是否有要合并的更改?

  • 您可以获取所有涉及的存储库(或推/拉/提交它们),在获取后,UI会更新为新的存储库状态,如果存储库发生了分歧,您可以看到冲突的种类并开始合并它们。

enter image description here

  

如何检查其中是否有未提交的更改?

  • 在UI上,您可以查看每个存储库的文件状态(您可以单独或批量添加/删除文件)。

enter image description here

我正在研究此问题,但这通常也可以解决OP问题并帮助管理多个存储库,您可以使用UI或底层的GraphQL API创建自己的脚本,请考虑将其作为另一种选择。

答案 19 :(得分:0)

我编写了一个名为gita的命令行工具来管理多个存储库。并排显示已注册存储库的状态,例如

enter image description here

它也可以从任何工作目录中委派git命令/别名。

现在使用此工具回答您的问题:

  

如何获取所有这些内容?

gita fetch
  

如何检查其中是否有未提交的更改?

gita ls命令在分支名称旁边显示3个可能的符号,表示

  • +:分阶段进行的变更
  • *:未进行的变更
  • _:未跟踪的文件/文件夹
  

如何检查其中是否有要合并的更改?

分支名称有5种颜色

  • 白色:本地分支没有远程分支
  • 绿色:本地分支与远程分支相同
  • 红色:本地分支与远程分支不同
  • 紫色:本地分支位于远程分支之前(有利于推送)
  • 黄色:本地分支位于远程分支后面(适合合并)

要安装它,只需运行

pip3 install -U gita

答案 20 :(得分:0)

您应该在CPAN上查看rgit,它在目录树中的所有存储库上递归执行git命令。

来自文档:

  

此实用程序递归搜索a   根目录(可能是   当前工作目录或 - 如果是   已设置 - 由...给出的目录   for GIT_DIR环境变量)   所有git存储库,对此列表进行排序   通过存储库路径,chdir进入   他们每个人,并执行   指定的git命令。

答案 21 :(得分:-1)

https://github.com/wwjamieson3/envisionTools有一个名为gitstat的bash脚本可以执行此操作,还可以执行更多操作。它是GNU和mac兼容的。如果被问到,它可以从遥控器执行提取。它显示未跟踪,修改,添加,删除和暂存的文件。它与遥控器的区别在于通过显示遥控器和未发布的本地提交的未合并提交。它还可以以摘要或详细模式甚至HTML显示颜色编码结果。它使用locate而不是find,因为它的速度非常快,如果它变得太旧,它甚至会提示更新你的locate数据库。

答案 22 :(得分:-2)

看起来编写脚本很容易。基本上它需要迭代存储库,然后使用git ls-files,git diff和git log等命令。