运行git拉过所有的子目录

如何从共享父目录中更新多个git存储库,而不必cd到每个repo的根目录? 我有以下这些都是单独的git仓库( 不是子模块):

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

我想一次更新它们,或者至less简化我目前的工作stream程:

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

等等

在这种情况下从父目录, plugins运行以下:

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

澄清:

  • find . search当前目录
  • -type d查找目录,而不是文件
  • -depth 1表示一个子目录的最大深度
  • -exec {} \; 为每个查找运行自定义命令
  • git --git-dir={}/.git --work-tree=$PWD/{} pull git pull个人目录

为了玩弄发现,我推荐使用echo after -exec预览,例如:

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

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

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

要并行执行:

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

比利奥的解决scheme更低技术:

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

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

这应该会自动发生,只要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 

我使用这个:

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

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

mr实用程序(aka, myrepos )为这个问题提供了一个出色的解决scheme。 使用你最喜欢的包pipe理器来安装它,或者直接从github中获取mr脚本,并把它放在$HOME/binPATH上的其他地方。 然后, cd到由这些repos共享的父plugins文件夹,并创build一个基本的.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 ,etc mr help查看可能的结果。 有一个mr run命令作为pass-through,允许你访问不是直接由mr VCS命令(例如, mr run git tag STAGING_081220015 )。 而且你甚至可以创build自己的自定义命令来执行任意位的shell脚本来定位所有的回购站!

mr是一个非常有用的工具来处理多个回购。 由于plugins文件夹位于您的主目录中,因此您可能也对vcsh感兴趣。 与mr一起,它提供了一个pipe理所有configuration文件的强大机制。 请参阅Thomas Ferris Nicolaisen的博客文章 。

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

 ls | parallel git -C {} pull 

其实,如果你不知道子文件夹是否有git repo,最好的办法是让find你的回购站:

 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 } 

你可以试试这个

 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" \; 

前5个答案都没有为我工作,问题谈论目录。

这工作:

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

原始答案2010:

如果所有这些目录都是独立的git回购,你应该引用它们作为子模块

这意味着你的“起源”将是那个只包含subrepos'cms',' admin ',' chart '引用的远程repo“ plugins ”。

一个git pull然后git submodule update将实现你正在寻找的东西。


2016年1月更新:

使用Git 2.8(2016年第1季度),您将能够使用git fetch --recurse-submodules -j2并行获取子模块(!)。
请参阅“ 如何使用git clone –recursive来加速/并行下载git子模块? ”

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

 npm install gitfox -g g pull 

我用这个

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

Github上

既然你有一个共享的父目录,你可以简单的做

git do pull插件/目录

我结合了几点意见和答案的观点:

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

我谦卑的build设

  • 显示当前path(使用python,方便而且正常工作,请参阅如何获取文件的完整path? )
  • 直接查看.git子文件夹:在非git子文件夹中发出git命令的机会很less
  • 摆脱一些find警告

如下:

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

当然,你可以添加其他的git命令和附加的-execdir选项来find ,显示分支,例如:

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

如果你有很多使用git仓库的subdirs,你可以使用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 '