git - 拉入子模块,现在在子模块中有一个无关的提交
问题描述
ProjectB 是 projectA 的子模块。projectB 发生了一些开发,我更新了 projectA 的子模块以指向最新的 projectB 提交。为此,我将 projectB 的上游更改拉入了我的 projectA 子模块。我将更改提交给 projectA 中的子模块。我愉快地编码,但已经意识到我的 projectA 子模块的 git 状态是:
git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
# (use "git push" to publish your local commits)
#
nothing to commit, working directory clean
尽管从未对 projectA 子模块进行本地更改。我的子模块的 git 日志是:
git log --oneline --decorate
2703249 (HEAD, master) Bugfix L148: correctly filling raw_hitmap_neig_s
9f1db21 (origin/master, origin/HEAD) created QL2P.xml for MCgen
1a3dfe5 Changed column name of files for DB output.
...
2703249
是最新的 projectB 提交,这些我都没有在本地完成。我想知道在这种情况下如何解释 git log,以及如何摆脱我的 repo 中的无关提交(不对 projectB 的远程进行任何类型的更改)。
根据这篇文章,在从子模块的远程获取更新部分中,我认为问题的根源与我拉入子模块的事实有关,但我不明白为什么会导致额外的提交,或如何解决。
解决方案
如评论中所述(并已针对此答案进行了修复),您只需要:
cd projectB && git fetch
获取子模块的origin/master
更新。
原因是您的特定 Git 版本非常旧(Git 现在是 2.26)。低于 1.8.4 的 Git 版本(当然包括您的 1.8.3.1)有一个坏习惯,即origin/*
在各种情况下不更新名称,特别是包括使用git pull
.
长
每个 Git 都有某个存储库的独立副本。这包括子模块,它们只是 Git 存储库,将根据需要被一些更高级别的超级项目Git 存储库拉出。幸运的是,我们可以在这里忽略大部分子模块方面,因为它对我们正在讨论的一个特定问题没有影响。
虽然每个 Git 都是独立的——有自己的分支名称,独立于任何其他 Git 的分支名称——我们总是可以将一个 Git 连接到另一个 Git。我们通常通过将一些 Git 存储库连接到我们克隆的存储库来做到这一点。也就是说,我们通过运行. 如果我们再次连接到 URL,他们的Git 可能会有我们可以抓取的新内容。或者,如果我们有可以给他们的新东西,我们也可以这样做。不过,显然,我们将再次需要该 URL。git clone url
遥控器会为您记住 URL
Git 存储库会为您记住一个 URL。回想一下那个 URL,我们使用了一个remote,它只是一个简短的名称,例如origin
——事实上,第一个远程的标准名称,我们从中做了我们的git clone
,是 origin
。因此,大多数 Git 存储库都有一个origin
短名称,用于表示我们当时实际输入的任何 URL——或者,对于子模块,超级项目用来运行git clone
以创建子模块 Git 的 URL。
对于更复杂的情况,您可以添加更多遥控器:每个遥控器记住一个 URL。但我们只考虑一个远程案例。
连接 Git 的命令是git fetch
和git push
要将您的 Git 连接到另一个,您将运行git fetch
或git push
. 怎么样git pull
?好吧,git pull
它只是做两件事的包装器:它首先git fetch
为您运行:
该
git fetch
命令将您的 Git 连接到另一个 Git 并从中获取内容。您可以给它一个 URL、https://example.com/some/path/to/repo.git
或简称origin
— 更容易键入、易于记忆,并且有多种好处。或者你可以让 Git 找出它origin
是唯一的遥控器,然后运行git fetch
.该
git push
命令将您的 Git 连接到另一个 Git并向它们提供东西。与 一样git fetch
,您可以给它一个 URL,或者漂亮的短origin
远程名称。
换句话说,我们选择另一个 Git,以及转移的方向——没有双向的“从另一个 Git 获取东西并把东西交给另一个 Git”选项,尽管这样的东西可能很有用。如果我们想这样做,我们必须运行两个单独的命令。git fetch
这些操作也不是很对称,但无论如何我们只会看这里。
当您使用 时git fetch
,您的 Git 会连接到另一个 Git,并让它列出其所有分支和标签以及其他此类名称,以及有关它们的 Git 内部详细信息。1 如果您git fetch
自己运行,您的 Git 会查看此内容并默认获取它们的所有分支名称,然后重命名它们:例如,它们master
变为 your origin/master
。
然后,您的 Git 会获取他们拥有的任何新提交,而您没有,然后更新您的所有origin/*
名称。这些origin/*
名称是您的远程跟踪名称。2 它们是你的 Git 对其他 Git 分支名称的记忆,这是你的 Git 上次调用他们的 Git 并带来新东西的时候。
要使此重命名生效,您必须使用短远程名称。 如果您使用 URL,Git 不知道在其分支名称前面添加哪个远程名称!无论如何,短名称通常更容易输入,因此大多数人只使用短名称,并origin/*
更新他们的名称。
有时你可能并不想要所有的东西:origin/master
例如,如果你只想要 . 你可以让你的 Git 只查看它们的master
. 有时这可以节省一点时间:也许他们master
根本没有更新,或者有一个小更新,而他们develop
或experimental
分支有很多你不需要的新东西。
1.8.4 之前的 Git 版本在这里有所不同。 无论出于何种原因——Git 人在 1.8.4 之后改变了主意,我真的不明白他们在那之前的想法——他们设置了一些东西,以便在那些版本的 Git 中,git fetch origin master
没有更新origin/master
,但git fetch origin
确实更新了origin/*
.
1这在一些最新版本的 Git 中实际上是不同的,因为一些存储库有大量的分支和标签名称,如果你只是想这样做,这部分过程可能会浪费大量时间和网络带宽得到一件事。
2 Git 调用这些远程跟踪分支名称。不过,它们并不完全是分支名称,而且分支这个词在 Git 中已经被过度使用,所以我喜欢删除那个多余的词,并称它们为远程跟踪名称。远程和跟踪这两个词在 Git 中也被过度使用了,所以即使这样仍然不是很好,但我们必须给它们起个名字!
git pull
运行的git fetch
那个git pull
使用“只更新一个分支”选项。也就是说,它会计算出你的 Git 想要从他们的哪个分支中提取,并且只询问那个分支。然后它执行第二步,即运行第二个 Git 命令——通常是——将其git merge
实际合并到您自己的分支中。3
这是为了方便。毕竟,只做git fetch
一件事:从他们那里获取新的东西,更新(可能是在 1.8.4 之前的版本)origin/*
过程中的部分或全部名称,以便您的 Git 现在记住他们拥有的东西。这无助于您完成自己的工作,因为您自己的工作通常发生在您的分支上。所以之后git fetch
,你需要第二步:将他们的工作混合到我的分支中。第二步可能使用git merge
,或者可能使用git rebase
,或者你甚至可能做一些完全不同的事情——也许创建一个你自己的新分支——但几乎总是有第二步。
因此,git pull
,git fetch
然后运行第二个 Git 命令。你可以——并且必须——提前选择第二个 Git 命令是git merge
还是git rebase
,而不知道会出现什么。我不是特别喜欢git pull
,但是对于一些定义明确的工作流程,它确实是更方便,如果它适合你,那很好。
然而,碰巧的是,在1.8.4之前git pull
的 Git 版本中,运行git fetch
的方式是你的origin/*
名字肯定不会更新。因此,您每次都会遇到这种特殊行为。
如果您升级到 1.8.4 或更高版本,git pull
将更新一个远程跟踪名称 - 例如,<code>origin/master - 对应于它获取的分支名称。或者,您可以避免git pull
,就像我在 Git 1.6、4 时代学到的那样,只需手动执行这两个步骤。
3在使用子模块的时候,这个合并操作往往是完全不需要的。现代 Git 中的子模块支持比这些非常旧版本的 Git 中的子模块支持要好得多,您现在可以使用git submodule
命令来获取更新,而不是手动一次进入每个子模块。即便如此,即使在现代 Git 中,它仍然有点粗糙,人们称这些sob模块是有原因的。:-) 细节可能会变得非常混乱。
4那时,git pull
有一些坏的错误。我失去了他们几周的工作。据我所知,那些虫子再也没有回来,但由于我大多避免git pull
,我不会看到它们。
推荐阅读
- firebase - 颤振错误 Firebase/Firestore- 空值检查运算符用于空值
- solidity - 如何获得从 Solidity 到 Web3 的“真实”块哈希
- c# - 如何从 C# foreach 中删除重复值?
- android - 操作栏颜色总是黑色?
- javascript - 使用 Javascript 从 IE 打印 ActiveX 元素
- c - 使用 MSVC 从 Windows Powershell 编译 C 程序
- javascript - 尝试更新 amCharts 4 中的数据时未捕获的 ReferenceError
- sql - 完全外部联接中缺少行
- python - Python 脚本未通过 pm2 start 命令从 Jenkins 管道启动
- excel - 识别表中人员配备变化的类型