运行git将所有子目录拉出来

我如何从他们的共享父目录更新多个git存储库而不__abc0 '到每个repo的根目录?我有以下所有单独的git存储库(子模块):

/plugins/cms
/plugins/admin
/plugins/chart

我想一次更新它们,或者至少简化我当前的工作流程:

cd ~/plugins/admin
git pull origin master
cd ../chart
git pull

等。

160222 次浏览

这应该是自动发生的,只要cms, admin和chart都是存储库的一部分。

一个可能的问题是这些插件都是git子模块。

运行git help submodule获取更多信息。

编辑

在bash中这样做:

cd plugins
for f in cms admin chart
do
cd $f && git pull origin master && cd ..
done

2010年原答案:

如果所有这些目录都是独立的git repo,则应该将它们引用为submodules

这意味着你的“起源”将是远程回购'plugins',它只包含对子回购'cms', 'admin', 'chart'的引用。

git pull后跟git submodule update将实现你所寻找的。


2016年1月更新:

使用Git 2.8(2016年第一季度),你将能够用git fetch --recurse-submodules -j2并行获取子模块(!) 参见“如何加速/并行下载的git子模块使用git克隆-递归?”< / p >

从父目录plugins运行以下命令:

find . -type d -depth 1 -exec git --git-dir={}/.git --work-tree=$PWD/{} pull origin master \;

澄清:

  • find .搜索当前目录
  • -type d查找目录,而不是文件
  • -depth 1用于一个子目录的最大深度
  • -exec {} \;为每次查找都运行一个自定义命令
  • git --git-dir={}/.git --work-tree=$PWD/{} pull git提取单个目录

为了更好地使用find,我建议在-exec之后使用echo进行预览,例如:

find . -type d -depth 1 -exec echo git --git-dir={}/.git --work-tree=$PWD/{} status \;

注意:如果-depth 1选项不可用,请尝试-mindepth 1 -maxdepth 1

比里奥的解决方案更低技术含量:

for i in */.git; do ( echo $i; cd $i/..; git pull; ); done

这将更新工作目录中的所有Git存储库。不需要显式列出他们的名字(“cms”,“admin”,“chart”)。“cd”命令只影响子shell(使用圆括号派生)。

ls | xargs -I{} git -C {} pull

并行地做:

ls | xargs -P10 -I{} git -C {} pull

你可以试试这个

find . -type d -name .git -exec sh -c "cd \"{}\"/../ && pwd && git pull" \;

此外,您还可以通过添加一个&&论点。

find . -type d -name .git -exec sh -c "cd \"{}\"/../ && pwd && git pull && git status" \;

如果你有很多git仓库的子dirs,你可以使用parallel

ls | parallel -I{} -j100 '
if [ -d {}/.git ]; then
echo Pulling {}
git -C {} pull > /dev/null && echo "pulled" || echo "error :("
else
echo {} is not a .git directory
fi
'

mr实用程序(也就是myrepos)为这个问题提供了一个杰出的解决方案。使用你最喜欢的包管理器安装它,或者只是抓取mr脚本myrepos0,并将其放在$HOME/bin或你的PATH的其他地方。然后,将cd放到这些repo共享的父文件夹plugins中,并创建一个基本的.mrconfig文件,其内容类似于以下内容(根据需要调整url):

# File: .mrconfig
[cms]
checkout = git clone 'https://<username>@github.com/<username>/cms' 'cms'


[admin]
checkout = git clone 'https://<username>@github.com/<username>/admin' 'admin'


[chart]
checkout = git clone 'https://<username>@github.com/<username>/chart' 'chart'

之后,你可以从顶层的plugins文件夹运行mr up从每个存储库中提取更新。(注意,如果目标工作副本还不存在,这也会执行初始克隆。)你可以执行的其他命令包括mr stmr pushmr logmr diff等——运行mr help来看看有什么可能。有一个mr run命令作为传递,允许你访问mr本身不直接支持的VCS命令(例如,mr run git tag STAGING_081220015)。您甚至可以创建自己的自定义命令,执行针对所有回购的任意shell脚本!

mr是处理多个回购的一个非常有用的工具。由于plugins文件夹在你的主目录中,你可能对vcsh也感兴趣。它与mr一起提供了一种强大的机制来管理配置文件的所有。请看Thomas Ferris Nicolaisen的博客概述。

最紧凑的方法,假设所有子dirs都是git回购:

ls | parallel git -C {} pull

我用的是这个:

find . -name ".git" -type d | sed 's/\/.git//' |  xargs -P10 -I{} git -C {} pull

通用:更新当前目录下的所有git存储库。

我用这个

for dir in $(find . -name ".git")
do cd ${dir%/*}
echo $PWD
git pull
echo ""
cd - > /dev/null
done

Github

前5个答案都不适合我,而且这个问题是关于目录的。

这工作:

for d in *; do pushd $d && git pull && popd; done

实际上,如果你不知道子文件夹是否有一个git repo,最好是让find为你获取repo:

find . -type d -name .git -exec git --git-dir={} --work-tree=$PWD/{}/.. pull origin master \;

PowerShell的等效代码是:

Get-ChildItem -Recurse -Directory -Hidden -Filter .git | ForEach-Object { & git --git-dir="$($_.FullName)" --work-tree="$(Split-Path $_.FullName -Parent)" pull origin master }

gitfox是一个在所有subrepo上执行命令的工具

npm install gitfox -g
g pull

我从一些评论和回答中总结了几点:

find . -maxdepth 1 -type d -name .git -execdir git pull \;

我的拙见是

  • 显示当前路径(使用python,方便且有效,参见如何获得文件的完整路径?)
  • 直接查找.git子文件夹:在非git子文件夹中发出git命令的机会很低
  • 去除find的一些警告

遵循:

find . \
-maxdepth 2 -type d \
-name ".git" \
-execdir python -c 'import os; print(os.path.abspath("."))' \; \
-execdir git pull \;

当然,你可以在find中添加其他带有额外-execdir选项的git命令,显示分支,例如:

find . \
-maxdepth 2 -type d \
-name ".git" \
-execdir python -c 'import os; print(os.path.abspath("."))' \; \
-execdir git branch \;
-execdir git pull \;