如何在不进入每个仓库的根目录的情况下,从它们共享的父目录中更新多个 git 仓库?以下是我拥有的这些独立的 git 仓库(不是子模块):
/plugins/cms
/plugins/admin
/plugins/chart
我希望能够一次性更新它们,或者至少简化我的当前工作流程:
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 .
搜索当前目录-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
。
find . -maxdepth 1 -type d -print -execdir git --git-dir={}/.git --work-tree=$PWD/{} pull origin master \;
这个命令来输出在执行pull之前文件夹的名称,以消除警告并只对子文件夹进行pull操作。 - Rystraumfetch origin master:master
会告诉git明确地使用origin的master分支更新你的'master'分支。这样做不会执行合并,如果这样做,将丢失对'master'分支的任何提交。 - ThorSummonerfind . -mindepth 1 -maxdepth 1 -type d -print -exec git -C {} pull \;
。 - Zaratls | xargs -I{} git -C {} pull
要并行地执行它:
ls | xargs -P10 -I{} git -C {} pull
all = "!f() { ls | xargs -I{} git -C {} $1; }; f"
现在我可以执行git all pull
、git all "checkout master"
等命令。 - borisdiakurls -R --directory --color=never */.git | sed 's/\/.git//' | xargs -P10 -I{} git -C {} pull
。 - cchamberlaingit config --global alias.all '!f() { ls -R -d */.git | sed 's,\/.git,,' | xargs -P10 -I{} git -C {} $1; }; f'
。 - Courtney Faulknerls -R -d */.git
返回的是当前文件夹中包含.git
目录的子文件夹列表。这样,当我运行类似于git all fetch
的命令时,它只会执行对包含.git
文件夹的子文件夹的操作。这是对原始问题的回答,但它尝试更加有效率,不假设所有子文件夹都是git存储库。 - Courtney Faulknergit config --global alias.all '!f() { ls -R -d */.git | xargs -I{} bash -c "echo {} && git -C {}/../ $1"; }; f'
- Jose Luis Blanco比Leo的解决方案略微低科技:
for i in */.git; do ( echo $i; cd $i/..; git pull; ); done
这将更新你的工作目录中的所有Git仓库。无需显式列出它们的名称(“cms”,“admin”,“chart”)。"cd"命令仅影响子Shell(使用括号生成)。
git -C
:for i in */.git; do git -C $i pull; done
- Jon-Eric实际上,如果你不知道子文件夹是否有git仓库,最好让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 }
gci | where {$_.Attributes -match'Directory'} | foreach { write-host $_.fullname; push-location $_; & git pull; & cd ..}
- jlohidden
的参数,但似乎 Force
可以工作,例如 Get-ChildItem -Path "C:\Repos" -Recurse -Directory -Force -Filter ".git" -Depth 1
。 - sommmen我使用这个:
find . -name ".git" -type d | sed 's/\/.git//' | xargs -P10 -I{} git -C {} pull
通用:更新当前目录下所有Git仓库。
--git-dir
替代 -C
直接传递 .git
路径,从而省去了 sed 替换的步骤!find . -name ".git" -type d | xargs -P10 -I{} git --git-dir={} pull
- Chris--work-tree
的情况下使用 --git-dir
是很危险的,这就是为什么创建了 -C
快捷方式。我之前因此搞乱了我的主目录。我建议只需执行 find . -maxdepth 8 -type d -name .git | xargs -P8 -I{} git -C {}/../ fetch --all
即可。 - jaksco前五个答案对我都无效,而且问题是关于目录的。
这个方法有效:
for d in *; do pushd $d && git pull && popd; done
-C
选项。 - Travis Stevensfor d in *; do (cd $d && git pull --ff-only); done
。这种方法比-C更具普适性,适用于没有此选项的程序。请注意,在自动更新的情况下,--ff-only
是很好的选择;如果使用本地vim包管理,则可以使用它来更新vim插件。 - nponeccop只要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
/plugins
不是一个存储库。 - Petahcd ..
即可。 - Jamie Wongpushd
和 popd
命令,或将一组命令放在子 shell 中(当子 shell 退出时,您将留在原始目录中)。(cd dir; for ... done)
- Dennis Williamson假设所有子目录都是 Git 仓库,则最紧凑的方法为:
ls | parallel git -C {} pull
moreutils
包中。 - cmcgintymr
实用程序(又名myrepos
)为此问题提供了一个杰出的解决方案。使用您喜欢的软件包管理器安装它,或者直接从GitHub 获取mr
脚本并将其放在$ HOME / bin
或其他PATH
上的位置。然后,cd
到这些仓库共享的父级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 st
、mr push
、mr log
、mr diff
等,运行mr help
查看可能性。还有一个mr run
命令作为一个通行证,允许您访问不直接受mr
支持的VCS命令(例如,mr run git tag STAGING_081220015
)。您甚至可以创建自己的定制命令,执行针对所有存储库的任意位shell脚本!
mr
是处理多个存储库的极其有用的工具。由于plugins
文件夹在您的主目录中,因此您可能还对vcsh
感兴趣。与mr
一起,它提供了管理所有配置文件的强大机制。请参阅Thomas Ferris Nicolaisen的博客文章进行概述。
这是我的简单的构造:
.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 \;
git do pull
是什么意思? - Frode Akselsenhg mercurial
回答。 - Serge Stroobandtfind . -name .git -print -execdir git pull \;
是正确的。-print
将会输出当前目录。 - DawnSonggit for-each-repo
命令,请参见 此处。 - VonC