Tha*_*tos 799 git git-pull git-submodules
我有一个带有Git子模块的项目.它来自ssh:// ... URL,并且在提交A.提交B已被推送到该URL,我希望子模块检索提交,并更改为它.
现在,我的理解是git submodule update应该这样做,但事实并非如此.它没有做任何事情(没有输出,成功退出代码).这是一个例子:
$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...
Run Code Online (Sandbox Code Playgroud)
我也试过git fetch mod,这似乎做取(但不能可能,因为它不要求输入密码!),但git log并git show否认新提交的存在.到目前为止,我刚刚rm对模块进行了重新添加,但这在原则上是错误的,在实践中也是乏味的.
Jas*_*son 1372
该git submodule update命令实际告诉Git您希望每个子模块检出已在超级项目的索引中指定的提交.如果要将子模块更新为其远程可用的最新提交,则需要在子模块中直接执行此操作.
总结如下:
# Get the submodule initially
git submodule add ssh://bla submodule_dir
git submodule init
# Time passes, submodule upstream is updated
# and you now want to update
# Change to the submodule directory
cd submodule_dir
# Checkout desired branch
git checkout master
# Update
git pull
# Get back to your project root
cd ..
# Now the submodules are in the state you want, so
git commit -am "Pulled down update to submodule_dir"
Run Code Online (Sandbox Code Playgroud)
或者,如果你是一个忙碌的人:
git submodule foreach git pull origin master
Run Code Online (Sandbox Code Playgroud)
Dav*_*d Z 424
Git 1.8.2提供了一个新选项--remote,可以实现这种行为.运行
git submodule update --remote --merge
Run Code Online (Sandbox Code Playgroud)
将从每个子模块的上游获取最新的更改,将它们合并,并检查子模块的最新版本.正如文档所说:
- 远程
此选项仅对update命令有效.不使用超级项目记录的SHA-1来更新子模块,而是使用子模块的远程跟踪分支的状态.
这相当于git pull在每个子模块中运行,这通常正是您想要的.
pin*_*nux 115
在您的项目父目录中运行:
git submodule update --init
Run Code Online (Sandbox Code Playgroud)
或者如果你有递归子模块运行:
git submodule update --init --recursive
Run Code Online (Sandbox Code Playgroud)
有时这仍然无法正常工作,因为在更新子模块时,您在本地子模块目录中进行了本地更改.
大多数情况下,本地更改可能不是您要提交的更改.这可能是由于子模块中的文件删除等原因造成的.如果是这样,请在本地子模块目录和项目父目录中重新运行:
git submodule update --init --recursive
Run Code Online (Sandbox Code Playgroud)
Mar*_*air 73
您的主项目指向子模块应该处于的特定提交.git submodule update尝试在每个已初始化的子模块中检出该提交是什么.子模块实际上是一个独立的存储库 - 只需在子模块中创建一个新的提交并推送它是不够的,您还需要在主项目中显式添加新版本的子模块.
因此,在您的情况下,您应该在子模块中找到正确的提交 - 让我们假设这是主要的提示:
cd mod
git checkout master
git pull origin master
Run Code Online (Sandbox Code Playgroud)
现在回到主项目,暂存子模块并提交:
cd ..
git add mod
git commit -m "Updating the submodule 'mod' to the latest version"
Run Code Online (Sandbox Code Playgroud)
现在推送您的新版主项目:
git push origin master
Run Code Online (Sandbox Code Playgroud)
从这一点开始,如果其他人更新了他们的主项目,那么master他们将更新子模块,假设它已被初始化.
Fre*_*ing 22
在本次讨论中,似乎有两种不同的场景混合在一起:
场景1
使用我的父repo指向子模块的指针,我想检查父repo指向的每个子模块中的提交,可能是在首次迭代所有子模块并从远程更新/拉取这些子模块之后.
正如所指出的那样,这是完成的
git submodule foreach git pull origin BRANCH
git submodule update
Run Code Online (Sandbox Code Playgroud)
场景2,我认为是OP的目标
在1个或多个子模块中发生了新的事情,我想1)拉出这些变化,2)更新父repo以指向这个/这些子模块的HEAD(最新)提交.
这将通过以下方式完成
git submodule foreach git pull origin BRANCH
git add module_1_name
git add module_2_name
......
git add module_n_name
git push origin BRANCH
Run Code Online (Sandbox Code Playgroud)
不太实用,因为你必须硬编码所有n个子模块的n个路径,例如脚本来更新父repo的提交指针.
通过每个子模块进行自动迭代,更新父repo指针(使用git add)指向子模块的头部会有什么好处.
为此,我制作了这个小的bash脚本:
git-update-submodules.sh
#!/bin/bash
APP_PATH=$1
shift
if [ -z $APP_PATH ]; then
echo "Missing 1st argument: should be path to folder of a git repo";
exit 1;
fi
BRANCH=$1
shift
if [ -z $BRANCH ]; then
echo "Missing 2nd argument (branch name)";
exit 1;
fi
echo "Working in: $APP_PATH"
cd $APP_PATH
git checkout $BRANCH && git pull --ff origin $BRANCH
git submodule sync
git submodule init
git submodule update
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
git commit -m "Updated $BRANCH branch of deployment repo to point to latest head of submodules"
git push origin $BRANCH
Run Code Online (Sandbox Code Playgroud)
要运行它,请执行
git-update-submodules.sh /path/to/base/repo BRANCH_NAME
Run Code Online (Sandbox Code Playgroud)
精
首先,我假设所有repo上都存在名为$ BRANCH(第二个参数)的分支.随意使这更复杂.
前几节是检查参数是否存在的一些部分.然后我拉出父回购的最新东西(我更喜欢使用--ff(快进)每当我做拉动时.我已经关闭了,顺便说一句).
git checkout $BRANCH && git pull --ff origin $BRANCH
Run Code Online (Sandbox Code Playgroud)
如果新的子模块已添加或尚未初始化,则可能需要进行一些子模块初始化:
git submodule sync
git submodule init
git submodule update
Run Code Online (Sandbox Code Playgroud)
然后我更新/拉取所有子模块:
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
Run Code Online (Sandbox Code Playgroud)
注意一些事情:首先,我正在使用链接一些git命令git add- 意味着前一个命令必须执行w/o错误.
在可能成功拉动之后(如果在遥控器上发现了新的东西),我做了一个推动,以确保在客户端上不会留下可能的合并提交.同样,只有发生如果拉新的东西实际上带来的.
最后,最后一步&&是确保脚本继续出错.为了使这项工作,迭代中的所有内容必须用双引号括起来,并且git-commands包含在parantheses(operator precedence)中.
我最喜欢的部分:
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
Run Code Online (Sandbox Code Playgroud)
迭代所有子模块 - 使用|| true,删除'Entering MODULE_PATH'输出.使用--quiet(必须使用单引号),子模块的路径将写入输出.
这个相对子模块路径列表在一个数组('echo $path')中捕获- 最后迭代这个并做$(...)更新父存储库.
最后,提交一些消息,解释父代表已更新.如果没有做任何事情,默认情况下将忽略此提交.把它推到原点,你就完成了.
我有一个在jenkins工作中运行它的脚本,之后链接到计划的自动部署,它就像一个魅力.
我希望这会对某人有所帮助.
Dan*_*ncă 18
简单明了,要获取子模块:
git submodule update --init --recursive
Run Code Online (Sandbox Code Playgroud)
现在继续将它们更新到最新的主分支(例如):
git submodule foreach git pull origin master
Run Code Online (Sandbox Code Playgroud)
Gab*_*les 12
# Option 1: as a **user** of the outer repo, pull the latest changes of the
# sub-repos as previously specified (pointed to as commit hashes) by developers
# of this outer repo.
# - This recursively updates all git submodules to their commit hash pointers as
# currently committed in the outer repo.
git submodule update --init --recursive
# Option 2. As a **developer** of the outer repo, update all subrepos to force
# them each to pull the latest changes from their respective upstreams (ex: via
# `git pull origin main` or `git pull origin master`, or similar, for each
# sub-repo).
git submodule update --init --recursive --remote
#
# For just Option 2 above: now add and commit these subrepo changes
# you just pulled
git add -A
git commit -m "Update all subrepos to their latest upstream changes"
Run Code Online (Sandbox Code Playgroud)
git submodule update --init --recursive
Run Code Online (Sandbox Code Playgroud)
git submodule update --init --recursive --remote
Run Code Online (Sandbox Code Playgroud)
...代替使用git submodule foreach --recursive git pull origin master或git submodule foreach --recursive git pull origin main。在我看来,上述两个选项的最佳答案是不要使用我在其他答案中看到的--merge和选项。--force
上面使用的选项的解释:
--init会初始化子模块,以防您刚刚克隆了存储库但尚未完成此操作--recursive对子模块内的子模块执行此操作,永远递归下去--remote表示将子模块更新到子模块的默认远程默认分支上的最新提交。例如,在大多数情况下,这就像对每个子模块执行git pull origin masteror操作。git pull origin main如果您想更新到最外层存储库(超级存储库)指定的提交,请不要这样做--remote。git submodule foreach --recursive git pull(不要使用这个——它经常失败)vs git submodule update --recursive --remote(使用这个!——它总是有效)我在这个答案下留下了以下评论。我认为它们很重要,所以我也将它们放入我的答案中。
基本上,对于某些情况,git submodule foreach --recursive git pull可能会起作用。对于其他人来说,git submodule foreach --recursive git pull origin master可能正是您所需要的。对于其他人来说,git submodule foreach --recursive git pull origin main可能就是您所需要的。而对于其他人来说,这些都可能不起作用!git submodule foreach --recursive git pull upstream develop例如,您可能需要。或者,更糟糕的是,可能没有任何 git submodule foreach命令适用于您的外部存储库,因为每个子模块可能需要不同的命令来从其默认远程和默认分支更新自身。然而,在所有情况下,我发现这确实有效,包括对于您可能使用我上面刚刚介绍的几个命令之一的所有情况git submodule foreach。所以,用这个代替:
git submodule update --recursive --remote
Run Code Online (Sandbox Code Playgroud)
无论如何,以下是我在这个答案下对此的几点评论:
(1/4) @DavidZ,很多人认为
git submodule foreach git pull和git submodule update --remote是同一件事,后者只是更新的命令。然而,它们不是同一件事。在多种情况下git submodule foreach git pull都会失败,但效果很好!如果您的子模块指向没有分支指向它的提交哈希(在现实开发中经常出现这种情况,您需要为外部存储库提供特定版本的子模块),那么该子模块...git submodule update --remote(2/4)...处于分离的 HEAD 状态。在这种情况下,
git submodule foreach git pull无法在该子模块上运行git pull,因为分离的 HEAD 不能有上游分支。git submodule update --remote但是,效果很好!它似乎调用git pull origin main该子模块 iforigin是默认远程并且main是该默认远程上的默认分支,或者git pull origin master,例如, iforigin是默认远程但是master默认分支。(3/4) 此外,在许多工作正常的
git submodule foreach git pull origin master情况下甚至会失败,因为许多子模块用作默认分支,并且许多其他子模块用作默认分支,因为 GitHub 从 更改为最近为了摆脱相关术语美国的奴隶制(“主人”和“奴隶”)。git submodule update --remotemastermainmastermain(4/4) 所以,我添加了显式的远程和分支,以更清楚地表明它们是经常需要的,并提醒人们,这
git pull经常是不够的,并且git pull origin master可能不起作用,并且git pull origin main当前者不起作用时可能会起作用,但也可能不起作用,并且它们本身都不与 相同git submodule update --remote,因为后一个命令足够智能,可以git pull <default_remote> <default_branch>为每个子模块执行操作,显然根据每个子模块的需要调整远程和分支。
git submodule说明:https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles#git-submodules-and-git-lfs-how-to-clone-this-repo-and-all-git-submodules-and-git-lfs-文件git submodule foreach <cmd>:/sf/answers/3202130781/man git submodule- 然后搜索foreach、--remote等。这对我来说可以更新到最新的提交
git submodule update --recursive --remote --init
注意,更新子模块提交的现代形式是:
git submodule update --recursive --remote --merge --force
Run Code Online (Sandbox Code Playgroud)
较旧的形式是:
git submodule foreach --quiet git pull --quiet origin
Run Code Online (Sandbox Code Playgroud)
除了...第二种形式不是真的“安静”。
See commit a282f5a (12 Apr 2019) by Nguy?n Thái Ng?c Duy (pclouds).
(Merged by Junio C Hamano -- gitster -- in commit f1c9f6c, 25 Apr 2019)
submodule foreach: fix "<command> --quiet" not being respectedRobin reported that
Run Code Online (Sandbox Code Playgroud)git submodule foreach --quiet git pull --quiet originis not really quiet anymore.
It should be quiet before fc1b924 (submodule: portsubmodulesubcommand 'foreach' from shell to C, 2018-05-10, Git v2.19.0-rc0) becauseparseoptcan't accidentally eat options then."
git pull" behaves as if--quietis not given.This happens because
parseoptinsubmodule--helperwill try to parse both--quietoptions as if they are foreach's options, notgit-pull's.
The parsed options are removed from the command line. So when we do pull later, we execute just thisRun Code Online (Sandbox Code Playgroud)git pull originWhen calling submodule helper, adding "
--" in front of "git pull" will stopparseoptfor parsing options that do not really belong tosubmodule--helper foreach.
PARSE_OPT_KEEP_UNKNOWNis removed as a safety measure.parseoptshould never see unknown options or something has gone wrong. There are also a couple usage string update while I'm looking at them.While at it, I also add "
--" to other subcommands that pass "$@" tosubmodule--helper. "$@" in these cases are paths and less likely to be--something-like-this.
But the point still stands,git-submodulehas parsed and classified what are options, what are paths.
submodule--helpershould never consider paths passed bygit-submoduleto be options even if they look like one.
And Git 2.23 (Q3 2019) fixes another issue: "git submodule foreach" did not protect command line options passed to the command to be run in each submodule correctly, when the "--recursive" option was in use.
See commit 30db18b (24 Jun 2019) by Morian Sonnet (momoson).
(Merged by Junio C Hamano -- gitster -- in commit 968eecb, 09 Jul 2019)
submodule foreach: fix recursion of optionsCalling:
Run Code Online (Sandbox Code Playgroud)git submodule foreach --recursive <subcommand> --<option>leads to an error stating that the option
--<option>is unknown tosubmodule--helper.
That is of course only, when<option>is not a valid option forgit submodule foreach.The reason for this is, that above call is internally translated into a call to submodule--helper:
Run Code Online (Sandbox Code Playgroud)git submodule--helper foreach --recursive \ -- <subcommand> --<option>This call starts by executing the subcommand with its option inside the first level submodule and continues by calling the next iteration of the
submodule foreachcallRun Code Online (Sandbox Code Playgroud)git --super-prefix <submodulepath> submodule--helper \ foreach --recursive <subcommand> --<option>inside the first level submodule. Note that the double dash in front of the subcommand is missing.
This problem starts to arise only recently, as the
PARSE_OPT_KEEP_UNKNOWNflag for the argument parsing ofgit submodule foreachwas removed in commit a282f5a.
Hence, the unknown option is complained about now, as the argument parsing is not properly ended by the double dash.This commit fixes the problem by adding the double dash in front of the subcommand during the recursion.
| 归档时间: |
|
| 查看次数: |
540583 次 |
| 最近记录: |