git - git remote update origin --prune 对本地更改的影响
问题描述
请注意:我首先看了一下这个问题,希望它能回答我的问题,但我认为我的问题略有不同!
有人告诉我,在git remote update origin --prune
本地运行会迫使我的本地仓库拥有与原始仓库完全相同的分支。但是,我可以找到有关使用的大量信息/文档git remote prune origin
,但不是git remote update origin --prune
...
我对这个命令的理解正确吗?如果不是,我怎么被误导了?如果我是正确的,那么如果我有尚未远程推送的本地功能分支会发生什么?如果我对远程/在源上存在的分支进行了更改,但我还没有推送这些更改,会发生什么?
提前致谢!
解决方案
TL;博士
命令与命令相同。(在某些版本的 Git 中有一些错误使它们不同,但它们应该做同样的事情。)使用,更新过程只是删除存储库中存在的任何远程跟踪名称,但不再对应于存储库中的分支名称。git remote update remote
git fetch remote
--prune
remote
长
有人告诉我,在
git remote update origin --prune
本地运行会迫使我的本地仓库拥有与原始仓库完全相同的分支。
这不太对。嗯,这根本不对,真的。这确实与您表达问题标题的方式有关:
影响……对局部变化
使用 Git 时,重要的是要识别出一些与大多数其他版本控制系统不同的地方。首先是分支,或者更准确地说是分支名称,并没有那么重要。分支名称喜欢master
并且develop
主要仅供人类使用,您可以对它们做几乎任何您想做的事情,包括任意更改它们。(我们稍后会谈到一些例外情况。)
你不能改变的——对 Git 来说真正重要的是提交哈希 ID。您将在git log
输出中看到这些内容:它们是大而难看的数字和字母字符串,例如b5101f929789889c2e536d915698f58d5c5c6b7a
,这是 Git 存储库中的一个提交。这些数字(实际上是十六进制表示)是唯一且通用的:每个地方的 Git 都会使用该数字进行该提交。如果您没有使用此特定 Git 存储库的克隆,则不会有该提交。如果您正在使用此特定 Git 存储库的克隆并且没有此提交,则您的 Git 只需要连接到另一个 Git有这个提交,你就会得到这个提交。
这些数字是 Git 识别和查找提交的方式。它们是 Git 真正关心的:提交本身,以及用于识别它们的唯一哈希 ID。
每个提交都包含一些其他早期提交的哈希 ID。通常每个提交只有一个较早的提交哈希 ID。那个较早的提交 ID 是提交的父级。因此,给定一些提交哈希 ID,您的 Git 可以判断您是否有提交。如果是这样,你的 Git 可以找出父哈希 ID,并告诉你是否有那个提交,然后找出它的父 ID,等等。这意味着给定任何一个提交(通过哈希 ID),您的 Git 可以找到所有提交,一个接一个,向后工作。这为绘制它们提供了一种简单的方法:
... <-F <-G <-H
whereH
代表一些提交哈希。Git 会找到实际的提交,读出它的父哈希 ID G
,读取提交,找到它的父F
,等等。当 Git 返回到第一个没有父哈希的提交时,该操作停止。
任何提交中的任何内容都不会改变。(部分原因是,实际的哈希 ID 是提交的所有内容的加密校验和。如果您要更改任何内容——甚至是一个位——您将获得一个新的、不同的哈希用于新的、不同的提交.) 因此,由于H
store 的G
哈希 ID,H
将永远,永远,指向G
. 因此,连接箭头的单向性几乎是无关紧要的,我们可以停止绘制它们;我们只需要记住 Git 本身必须向后工作。
分支名称,如master
or ,只是 Git 提供的一种develop
方式,可让您帮助记住其中一个哈希 ID。它只记得其中一个!根据定义,它记得的那个是最新的。如果您更改与您的 关联的数字master
,您已经告诉您的 Git:使用不同的提交作为最新的提交。 因此,我们对图片进行了一些扩充:
...--F--G--H <-- master
因此,其中的哈希 IDH
是Git 应视为“on”分支的最后一次master
提交的 ID 。
当您进行新的提交时,从git checkout master
所有通常的事情开始并执行到您运行的点git commit
,Git 会写出一个新的提交。这个新的提交获得了一个新的、唯一的哈希 ID,我们可以称之为I
:
...--F--G--H <-- master
\
I
写出提交并找到其加密校验和哈希 ID 后,Git 现在将该哈希 ID 写入 namemaster
中,因此master
指向I
:
...--F--G--H
\
I <-- master
现在I
是master
. 你/你的 Git 仍然可以通过从上一步H
开始并返回来找到 commit 。I
如果某些东西要覆盖你master
并让它指向 back H
,那么很难找到commit I
,因为内部箭头都指向后面。 I
指向H
——孩子知道它的父母——但H
根本不知道I
存在。(当谁创造了H
,创造了它,H
现在不能改变时,它就没有了!)
出于这个原因(以及其他原因),您的分支名称是yours。除了您和您的 Git 之外,没有人可以将新数字写入其中。实际提交的哈希 ID 是唯一且通用的:如果其他人进行了新提交,则该新提交将获得一个其他提交永远不会拥有的新哈希 ID,并且您的 Git 会知道您是否有该提交。如果您需要它,当您将 Git 连接到他们的 Git 时,您的 Git 将从他们的 Git 获取它。但你的分支名称是你的。
所以git fetch
或者git remote update
——同样,两者都做同样的事情——将调用其他一些Git,并从它们那里获得你没有的任何新提交。假设您git fetch origin
在您正在调用的 URL 处调用 Git origin
。如果您将提交添加I
到您的master
,并且他们将提交添加J
到他们的,那么您的 Git 现在具有:
...--F--G--H--J <-- ???
\
I <-- master
你的 Git 将如何找到提交J
?将那个哈希 ID 写入你master
的显然是一个坏主意:那输了I
!那么您的 Git可以在哪里写入该哈希 ID?
Git 对此的回答是远程跟踪名称(大多数人称之为远程跟踪分支,但我认为 Git 已经过多地使用了分支这个词)。你的 Git 的名字,你的 Git 会记住origin
's master
,是origin/master
,图片应该是:
...--F--G--H--J <-- origin/master
\
I <-- master
如果你想向他们的I
主人添加提交——或另一个同样好的提交——你现在必须决定,你真的想要它自己,还是另一个同样好的提交?如果你想保留自己,你会合并并做出一个有两个父母的新提交:I
I
I
J
...--F--G--H--J <-- origin/master
\ \
I--M <-- master
由于合并提交M
有返回到和的箭头, J
您 I
现在可以向他们发送提交M
并要求他们的 Git 将他们 master
的指向点设置为提交M
。
你的 Git 的每个分支都有一个远程跟踪名称
当你运行git fetch origin
orgit remote update origin
时,你的 Git 会调用另一个 Gitorigin
并询问其所有分支的列表。他们的分支当然是他们的,但是你的 Git 想要获得他们所做的任何新提交,并为你记住最新的提交。因此,如果他们有master
, develop
, feature/A
, 和feature/B
, 你的 Git 会得到他们有的任何你没有的提交,并记住他们的分支提示在你的origin/*
名字下,对应于他们的分支名称:
L--N <-- origin/feature/A
/
...--F--G--H--J <-- origin/master
\
I <-- master
如果他们故意通过将较旧的哈希 ID 写入其分支名称来从某些分支中删除某些提交,您的 Git 将相应地调整您的远程跟踪分支。在某些情况下,这可能会导致你的 Git 忘记他们的提交(如果你从来没有费心用自己的名字来保存它们):
N [abandoned]
/
L <-- origin/feature/A
/
...--F--G--H--J <-- origin/master
\
I <-- master
CommitN
不再是可找到的,并且最终git gc
会将其从您的存储库中完全删除。(这是分支名称或其他名称变得重要的地方:它们不仅可以让您找到提交,它们还可以保护来自死神收集器的提示提交。这些提示提交保护他们的父母,他们保护链中更靠后的提交,一直到根提交。)
但是,假设他们在某个时候决定该功能A
已完成。他们已经将它合并回他们的主人,或者快进他们的主人直接指向它:
...--F--G--H--J--L <-- master, feature/A [no origin/ -- this is THEIR Git!]
在你的 Git 中是:
...--F--G--H--J--L <-- origin/master, origin/feature/A
\
I <-- master
他们现在可以完全删除他们的feature/A
名字。当他们这样做时,您的Git 将停止为您的origin/feature/A
.
但是,如果没有--prune
,您的 Git *不会删除您的origin/feature/A
. 因此,您继续记住origin/feature/A
指定 commit L
。这不会造成任何真正的伤害。根据您的origin/*
名字,您只会认为他们仍然拥有feature/A
并且这意味着 commit L
。
是否使用--prune
取决于您。我在自己的 Git 配置中自动打开它;这使我的存储库不那么混乱。
推荐阅读
- python - 在 Python 中查找输入字符串到元组列表的所有可能匹配项(以任何顺序/顺序)
- html - Favicon Html 不显示
- powerbi - PBIX 文件与 Power BI Desktop 中的编辑
- java - 在这种情况下如何避免类型检查参数
- apache-flink - How to stop Apache Flink CEP Pattern?
- vue.js - 创建一个包含 SCSS 的节点 (vue.js) 模块
- java - 如何自动将文件从一个服务器位置复制到另一个位置并从源位置移动?
- r - Dplyr 将活动日期数据重塑为每月级别
- java - 如何在 JAVA 中将 HTTP 标头添加到 SOAP 端点 uri?
- java - maven 适用于 windows powershell 和 cmd,但不适用于 git bash