管理许多git仓库


85

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

我在这些存储库中的多个地方工作。完成对某些存储库的更改后,我希望能够在其他位置更新存储库。

因此,我有一个包含许多存储库的目录。

  1. 如何获取所有这些?
  2. 如何检查其中是否有未提交的更改?
  3. 如何检查其中是否有要合并的更改?

能够使用一个命令完成这些操作就很好了。

输出必须足够安静以实际注意到要执行的操作。


回答了相同的问题hg mercurial
Serge Stroobandt

Answers:


44

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

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

关于您有关静默输出的问题:可以使用命令行开关-q修改详细级别。我更喜欢默认输出,它看起来似乎可以在简短明了的摘要中很好地统一输出。

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

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

5
它支持Windows吗?
Fitzchak Yitzchaki

很棒,但不支持git标签(截至2016
Hugo Zaragoza

@CADbloke在安装页面中没有提到Windows,但是作为Perl脚本,它可能/应该/可以在Windows上工作。
scipilot'4

2
@HugoZaragoza,您始终可以自行定义此命令[DEFAULT] tag = git tag“ $ @”
AlexS

2
alias pa='find . -name .git -print -execdir git pull \;'那么pa就足够了
DawnSong 18/12/29

19

我必须说我从当前接受的答案开始(只是一堆遍历存储库的帮助程序脚本),但是总的来说,这对我来说是缺乏经验。

因此,在尝试了mr,repo和git-submodules之后,我发现每个缺少的方式都不同,因此,我最终做了自己的变体:http : //fabioz.github.io/mu-repo,它是成熟的工具,位于至此-它具有允许您执行以下操作的工作流程:

  • 克隆多个存储库
  • 比较(和编辑)多个存储库中的当前更改
  • 预览即将到来的更改
  • 在多个存储库中并行运行命令
  • 创建存储库组
  • 在多个存储库上运行非git相关命令
  • 等等(更多信息,请参见首页)。

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


您的回答表明,mu-repo比mr-repo更好。但是mu-repo不支持非git repos。
Shaunak Sontakke

1
Whell,它的目的实际上是仅支持git repos(这是要问的问题)-尽管您也可以mu sh <some command>在多个repos中执行一些任意命令,但是它的最终确定性是在处理git而不是其他版本控制系统。 。如果需要,请使用其他工具。
Fabio Zadrozny

14

gr(git-run)扩展了mr的功能(仅用于git)。我发现使用其标记系统来组织多个git repos更容易。的代码gr维护得不好。如果您正在使用bash,请确保将其与-t tag而不是#tag表单一起使用。


从那以后看来,发展已经有所回升:github.com/mixu/gr/graphs/contributors
Dave Forgac

8

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

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


2
如果我想将存储库保持在完全相同的状态,那么git-submodule会很好,但是事实并非如此。每个地方的存储库集都不相同。可能有未提交的更改。可能有一些我不想合并的更改。
2009年

我不知道git-submodule。感谢您提及。
sykora

回购的文档非常少,看起来像是针对我想使用的其他类型的工作流程。
2009年

6

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

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

RepoZ UI

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

RepoZ导航

“我该如何取回它们?”

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

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

RepoZ自动提取

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


是的,太糟糕了,不应该得到。随时开放PR。ping我
Waescher

5

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

这通常用于需要将多个存储库组装在一起并同时将它们存储在同一分支或标签上的项目。对于我的(裸)存储库目录,我只有一个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

我做了一个别名和一个函数,以在目录中可用的所有存储库上(递归地)运行任何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 "$@" \;
}

希望能帮助到你 :)


1
苗条而有用!
凯文·周

太棒了!简单的单线可放入.bash_aliasesalias rgit='function _rgit(){ find . -type d -name .git -printf "\n%p\n" -execdir git "$@" \;; }; _rgit'。来源,然后例如call rgit status
ford04

4

您可以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状态全部


1
非常好的方法。与大多数获得较高投票权的工具相比,无需先注册存储库,只需检查所有子目录即可。
luator

find . -name .git -print -execdir git status \;可以
DawnSong

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环境变量设置为自己喜欢的方式来覆盖它。

该脚本基于此脚本


find . -name .git -print -execdir git pull \;做到了你的想法。
DawnSong

3

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

在此处输入图片说明

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

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

如何获取所有这些?

gita fetch

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

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

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

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

分支名称有5种颜色

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

要安装它,只需运行

pip3 install -U gita

2

如果有人仍在查看此线程,请签出我的名为gitme的shell脚本

您将需要手动输入本地git仓库,但我每天都使用此工具在多台计算机上协作多个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'


1

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

从文档:

该实用程序在根目录(可能是当前工作目录,或者-如果已设置-GIT_DIR环境变量给定的目录)中递归搜索所有git存储库,并按存储库路径chdir对该目录进行排序它们,并执行指定的git命令。



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.

也可以使用以下命令并行运行它们:all'./gradlew clean test&'
ChaudPain

0

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

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

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

在此处输入图片说明

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

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

在此处输入图片说明

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


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


0

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

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

这是它的屏幕截图:

VS Code中的源代码管理窗口


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 rev-parse ...为当前分支的目录指定分支,同时执行git pull origin HEAD提交。

{} \;

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

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

您可以修改它以获取状态。我希望您可以添加参数以进一步使此方法更加灵活,但我还没有尝试过。


-1

https://github.com/wwjamieson3/envisionTools具有一个名为gitstat的bash脚本,可以执行此操作以及更多其他功能。它与GNU和Mac兼容。如果要求,它可以从远程执行获取。它显示未跟踪,修改,添加,删除和暂存的文件。它通过显示未合并的远程提交和未推送的本地提交而与远程服务器不同。它还可以以摘要或详细模式甚至HTML显示颜色编码的结果。它使用locate而不是find,因为它速度无限快,并且如果它已经太旧了,甚至会提示您更新locate数据库。


2
感谢您发布答案!请务必仔细阅读有关自我促销常见问题解答。另请注意,每次链接到您自己的站点/产品,您都必须发布免责声明。
Andrew Barber 2012年

3
不幸的是,github wwjamieson3 / envisionTools链接已损坏。
布伦达·J·巴特勒

@williamJamieson是envisionTools是私有GitHub存储库吗?
eebbesen

-5

看起来编写脚本来做到这一点很容易。本质上,它需要遍历存储库,然后使用git ls-files,git diff和git log之类的命令。


我知道已经晚了,但是您可以发布脚本吗?
09年

没有“脚本”。我使用的是为满足自己的需要而编写的脚本,但这不是通用的。
2009年

如果您想获得一个可以通过单个patch命令还原并重新应用的diff文件,那么“ git diff”实际上就很棘手。
2015年

4
从字面上看,任何答案都应该是公认的答案,但这是可以的。
Kennet Celeste
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.