Managing many git repositories

Setting up a project is easy in git and so I can have separate repository even for small script. Now the problem is how to manage them.

I work in multiple places with these repositories. When I have done changes to some repository, I want to be able to update the repositories in other places.

So I have a directory with many repositories in it.

  1. How can I fetch all of them?
  2. How can I check whether any of them have uncommitted changes?
  3. How can I check whether any of them have changes to merge?

And it would be nice to be able to do these with one command.

The output needs to be silent enough to actually notice the things to do.

58600 次浏览

您可以尝试使用 回购和自定义 manifest.xml文件来指定存储库的位置。关于如何做到这一点,有 更多的文件

It's the standard for Android AOSP 项目.

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

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

From the docs:

此实用工具在 根目录(可能是 目前的工作目录 has been set - the directory given by 环境变量) 所有 git 存储库,对这个列表进行排序 通过存储库路径,chdir 变成 并执行 指定的 git 命令。

看起来写一个脚本来做这件事很容易。实际上,它需要遍历存储库,然后使用 git ls-files、 git diff 和 git log 等命令。

我使用这个脚本轻松地在所有存储库中执行 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 环境变量来覆盖它。

此脚本基于 这个剧本

I highly recommend the multiple repositories tool 先生. I used to use a custom shell script as recommended by others for some time, but using mr has the following benefits for me:

  • 它是通用的: 不仅可以使用 git (例如 Mercurial、 SVN 等) ,还可以使用各种版本控制系统的连接。
  • 它的速度很快: Mr 可以并行执行多个作业。我使用了许多 git/mercurial 存储库,并且每天对它们进行多次同步。先生极大地加快了这个过程。
  • 管理存储库签出列表非常简单快捷。只要使用“ Mr register”,而不是修改自定义脚本中的项目列表。

关于您关于静默输出的问题: 可以使用命令行 switch-q 修改详细级别。

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

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

GitSlave 是一个工具,它可以通过在 super 和 subs 之间创建一个超级项目/子项目关系,在许多存储库上运行相同的命令。这(默认情况下)提供了输出摘要,这样您就可以专注于提供惟一输出的存储库(对于 git status 有用,对于 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

我必须说,我从当前接受的答案开始(只是一些在存储库上迭代的帮助脚本) ,但总的来说,这对我来说是一种缺乏经验的体验。

所以,在尝试了 Mr. repo 和 git 子模块之后,我发现每个模块都有不同的缺陷,所以,我最终做了自己的变体: http://fabioz.github.io/mu-repo,这是一个成熟的工具,它有工作流,允许你:

  • 克隆多个回购协议
  • Diff (和编辑)当前在多个回购协议中的变化
  • 预览传入的更改
  • 在多个回购协议中并行运行命令
  • 创建回购协议组
  • 在多个回购协议上运行与 git 无关的命令
  • 等等(更多信息见 homepage)。

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

https://github.com/wwjamieson3/envisionTools has a bash script called gitstat that does this and a whole lot more. It's GNU and mac compatible. It can perform fetches from remotes if asked. It shows untracked, modified, added, deleted and staged files. It differences with remotes by showing unmerged commits on remotes and unpushed local commits. It also can display color coded results in summary or detailed mode and even HTML. It uses locate instead of find because it's infinitely faster and will even prompt to update your locate database if it's getting too old.

Gr (git-run)扩展了 强先生的功能(仅适用于 git)。我发现使用它的标签系统更容易组织多个 git 回购协议。但是 gr的代码没有得到很好的维护。如果使用 bash,请确保将其与 -t tag而不是 #tag表单一起使用。

如果有人还在关注这个线程,请检查我的 shell 脚本 gitme

你将需要手动输入您的本地 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. 我怎样才能把它们全部取出来? gmaster fetch
  2. 如何检查它们中是否有未提交的更改
  3. 如何检查它们中是否有要合并的更改? gmaster status

它叫做 Gitmaster: https://github.com/francoiscabrol/gitmaster

可以使用 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

我将这个简单的 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.

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

Hope it helps :)

我编写了一个名为“ RepoZ”的工具,它可以在您克隆或更改 git 存储库(比如切换分支)时自动发现它们。

一旦找到存储库,就会对其进行“跟踪”。这将简单地将它们显示在一个本地存储库列表中,其中包括受 时髦的家伙启发而提供的密集状态信息。它包含当前分支和进一步的内容,比如文件编辑和传入或传出提交的计数。

RepoZ UI

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

RepoZ Navigation

“我怎么才能把它们都拿来?”

The version for Windows offers a context menu to fetch or pull a repository. With multi-select you can run actions on multiple repositories at once.

不过,您可能会发现另一个非常有用的特性:

RepoZ Auto-Fetch

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

我编写了一个名为 Gita的命令行工具来管理多个回购协议。例如,它并列显示已注册回购协议的状态

enter image description here

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

现在用这个工具回答你的问题:

How can I fetch all of them?

gita fetch

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

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

  • 分阶段更改
  • 未分阶段的更改
  • _: 未跟踪的文件/文件夹

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

分支名称以5种方式着色

  • 本地分支没有远程分支
  • 绿色: 本地分支与远程分支相同
  • 红色: 本地分支已经偏离了远程分支
  • 紫色: 本地分支领先于远程分支(适合推送)
  • 黄色: 本地分支位于远程分支之后(适合于合并)

要安装它,只需运行

pip3 install -U gita

免责声明: 我在 Www.repoflow.com工作这个工具

我怎么才能把它们都拿来?
如何检查它们中是否有要合并的更改?

  • 您可以获取所有相关的存储库(或者推/拉/提交它们) ,在获取之后,UI 将使用新的存储库状态进行更新,如果存储库分散,您可以看到这种冲突并开始合并它们。

enter image description here

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

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

enter image description here

I am working on this, but this is also solving the OP questions and help manage multiple repositories in general, you can use the UI or the underlying GraphQL API to create your own scripts, please consider it as another option.

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

安装

npm install -g git-pull-all

Usage

假设您有这些文件和目录:

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

当您在 ~/Projects目录上运行 git-pull-all命令时,它应该找到子 git 存储库(在上面的例子中是 很酷的例子超快) ,然后在每个子 git 存储库上执行 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

我使用 Visual Studio 代码。我们的代码库中有大约20个库,它们都是独立的 Git 回购,Visual Studio Code 中的源代码控制选项卡非常适合“一目了然”地查看本地回购的落后程度或领先程度。还有一些设置可以定期获取,以保持信息的最新性,以及一个刷新按钮。

Its not as convenient as a script, but when it comes to source control for me I like to be the one making changes. It takes a very well-written script to be careful to not overwrite changes, etc. With the VS Code approach, you get a good amount of info quickly that you can act on yourself.

下面是它的截图:

Source control window in VS Code

I've found a great solution for pulling from the current branch from all sub-directories that have a .git folder, even if each repo has a different branch checked out. 该命令是一行程序,足够灵活,可以针对不同的 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

在工作目录中查找所有目录(- type d)(Find.)有这个名字”。Git”(- 名称。Git) ,最多查找两个目录(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... 为当前分支的 HEAD 提交指定分支时,执行 git pull 原点。

{} \;

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

在 MacOS 10.14.6上在 zsh 上进行了测试,仅当远程分支和本地分支的名称相同时才能正常工作,即 AFAIK。

您可以修改它以获得状态。我希望你们能够添加一些论点来进一步使这个问题更加灵活,但是我还没有尝试过。

我使用我的代码编辑器(VS 代码)的多光标选择/多行编辑特性来创建批处理/shell 脚本并一次执行它。通过这个简单而愚蠢的解决方案,我知道自己在做什么,也知道执行这些命令能带来什么。不需要猜测,不需要学习,不需要定制。另一个原因是,每次我想对驻留在一个公共父目录中的不同回购协议集执行命令时。

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

npm i -g every-cli

Usage example: every git branch

- repo-1
master
- repo-2
develop

请按照下面提到的步骤从所有存储库中提取代码:

  1. create a new file using extension as .bat
  2. place that file in the same hierarchy where you have all your repository folders
  3. Bat 文件并添加下面提到的脚本
FOR /D %%G in (%cd%\*) Do cd %%G & call git branch & call git pull & cd ..
echo All code pulled successfully!!
pause
  1. 保存文件并双击以开始提取代码

我为此编写了一个 CLI 工具,参见 https://manicli.com/。它还有一些不错的附加特性:

  • 在许多回购协议上运行命令
  • Declarative configuration
  • 灵活的过滤,选择1个项目,项目有一个标签,或一个子路径

扩展 https://stackoverflow.com/a/816674/1869000(现在可以在 GitHub 上获得回购协议)

我建议你检查这个工具 https://github.com/googleapis/github-repo-automation使用的谷歌管理多个回购协议。

关于您关于专用更改的问题,更改应该是 PR,以便您可以对它们作出反应。

Https://github.com/tj/git-extras 可以帮助您为您的场景编写脚本。

  1. 我怎么才能把它们都拿来? 谷歌的解决方案

  2. 如何检查其中是否有未提交的更改? You can easily write your logic using the lib feature

  3. 如何检查它们中是否有要合并的更改? PR 应该是分支需要合并的最终指示,但是如果你有另一种逻辑——以上

检查 git 额外命令的想法见 https://github.com/tj/git-extras/blob/master/Commands.md#git-show-unmerged-branches