我最近一直在尝试了解有关 git 的更多信息。我想知道遥控器是什么,我找到了答案,很简单,然后我跑了git remote -v
,有两个具有相同的 url,但一个后跟(获取),另一个(拉)。所以
origin http://someurl_git/application (fetch)
origin http://someurl_git/application (push)
我只是想知道它是如何进入那种状态的?从我在另一个线程中读到的内容来看,有两个相同的 url 是不正常的。我想试着追溯一下,弄清楚它是如何变成这样的。以及这可能会导致什么问题。
然后我跑了:
git remote show origin
它列出了这个:
* remote origin
Fetch: origin http://someurl_git/application
Push: origin http://someurl_git/application
HEAD branch: master
Remote branches:
BranchA tracked
develop tracked
BranchB tracked
Local branches configured for 'git pull':
develop merges with remote develop
master merges with remote master
Local refs configured for 'git push':
develop pushes to develop (local out of date)
master pushes to master (up to date)
我的问题是:
为什么上面有一个具有相同网址的获取和推送?
">引用"和"分支"之间的相关性是什么? ref 是否仅表示我的推送将影响的远程分支?而本地上下文中的分支仅意味着..."拉动会影响当地分支机构" ?
"(本地过时)"和("最新")是什么意思?这是否意味着我的本地存储库中未反映在远程存储库中的任何更改?但是为什么它说"最新"的推动掌握?我认为它也会说同样的"远程/本地过时"。
我觉得我缺少一些术语,但如果没关系,我只是想避免任何问题,因为现在有更多的开发人员参与其中。
谢谢
1. 为什么上面有一个 Fetch 和一个 Push 具有相同的 url?
因为在某些设置中,可能需要从一个源拉取,但推送到另一个源。如果不是这种情况(默认情况下),则两者都具有相同的URL。这确实很正常。
2.a "refs"和"branches"之间有什么相关性?ref 是否仅表示我的推送将影响的远程分支?而本地上下文中的分支仅意味着..."拉动会影响当地分支机构" ?
引用是指向提交的指针。有两种类型的引用:分支和标签。
<小时 />3."(本地过时)"和("最新")是什么意思?这是否意味着我的本地存储库中未反映在远程存储库中的任何更改?但是为什么它说"最新"的推动掌握?我认为它也会说同样的"远程/本地过时"。
"(本地过期)"表示远程分支具有本地分支仍然不知道的新提交,而"(最新)"表示两者都指向同一提交。
Romain Valeri的回答直接涵盖了你的三个问题,但听起来你需要更多的背景信息。
。我想知道遥控器是什么...
我想说它主要是URL的简称。 不过,这掩盖了很多细节。这是一个名字——多久取决于你;使其简短,以便于键入,并且应至少存储一个 URL。 不过,它可以很容易地存储两个URL:一个是"获取"URL,另一个是"推送"URL。 您可以使用git remote set-url
或使用git config
来设置这些。 每个远程的 URL 都存储在一个唯一的键下。 如果远程数据库命名为origin
(通常第一个远程数据库是这样),则此键为:
remote.origin.url
,以及:
remote.origin.pushurl
作为推送网址。 如果未设置推送 URL(如果没有remote.origin.pushurl
键),则推送 URL 将自动与抓取 URL相同。
配置键位于.git/config
和$HOME/.gitconfig
或$HOME/.config/git
或类似文件中(配置文件的确切位置取决于系统)。 当我们使用git config
命令查询或设置它们时,它们具有这种点分隔形式,对于大多数其他用途,但在配置文件中,它们以修改后的 INI 文件格式存储。 Git 使用的修改格式如下所示:
[remote "origin"]
url = ssh://git@github.com/user/repo.git
fetch = +refs/heads/*:refs/remotes/origin/*
例如。[remote "origin"]
节标题下的这对条目定义了remote.origin.url
和remote.origin.fetch
。
有关配置文件的更多信息
Git 中的某些键值对是单值的。 例如,user.name
和user.email
设置以这种方式工作。 当你运行git commit
进行新提交时,Git 会运行git config --get user.name
的内部等效项来获取你的名字。
假设您的全局配置文件显示:
[user]
name = Fred Flintstone
email = fred@rockville.prehistory
但您的本地(Git 存储库中).git/config
文件显示:
[user]
name = Barney Rubble
(没有user.email
设置)。 运行的结果:
git config --get user.name
将Barney Rubble
,因为此处设置的本地设置将覆盖全局设置。 运行的结果:
git config --get user.email
将fred@rockville.prehistory
,因为没有本地设置,因此全局设置是唯一可用的设置。
其他键值对可以是多值的。 在这种情况下,每个设置都是可见的,但使用这些设置的 Git 程序必须运行内部等效项git config --get-all
而不是 htangit config --get
。 使用上述配置文件,运行:
git config --get-all user.name
会溢出两行:
Fred Flintstone
Barney Rubble
如果不查看每个单独的程序,就无法知道它是使用git config --get
还是git config --get-all
(或内部等效项)。 因此,如果您多次设置配置项目,您永远不会知道哪些命令可能使用所有设置,哪些命令将仅使用最后一个设置,除非它们在文档中告诉您。 有时你可以通过实验找到答案。 如果没有文档,您也无法判断现在或将来可能会使用哪些设置。 例如,您可以运行:
git config --global french.city paris
马上。Git 中目前没有任何内容使用此设置,因此您添加了:
[french]
city = paris
到您的全局 Git 配置不会影响今天的 Git 程序。 但是,如果某个 Git 程序明年开始使用该设置,那么您已经设置了它,因此它将在 2023 年执行该程序意味着它所做的任何操作。
这些设置是自由格式的事实使得引入拼写错误变得非常容易,并且永远不知道你已经这样做了。 请务必仔细检查设置!
git remote
计划
git remote
程序与许多 Git 命令一样,相当复杂。 它开始很简单,但随着时间的推移而增长。 它可以:
- 显示、添加、重命名或删除某些遥控器;
- 显示或设置遥控器的 URL;
- 显示或设置遥控器的多值
fetch
行; git fetch
运行到单个遥控器或多个遥控器;- "修剪"遥控器(这与
git fetch -p
相似,但略有不同); - 设置或删除任何给定遥控器的"头";或
- "显示"有关特定遥控器的信息。
这些操作中的大多数都不会调用有问题的远程,即它们不会通过网络联系另一组 Git 软件来查看其他一些 Git 存储库。 此规则的例外情况是:
update
(fetch),它必须调用远程以查找可能存在的新提交或其他新对象;prune
,这有点像获取;set-head
--auto
选项;和show
.
最后一个 -git remote show
-可选地调用遥控器。 默认设置是,如果给定远程的名称,它应该这样做;-n
标志可防止这种情况。
通过调用远程(git ls-remote
也可以这样做;尝试一下;请注意,它可能会产生大量输出,您可能希望通过寻呼机通过管道传输它),git show
命令可以找出远程上存在哪些分支名称。 这有助于它弄清楚git fetch
或git push
会做什么,如果你现在运行git fetch
或git push
。
当与-n
一起使用时,git show
命令实际上无法实现这一点。 这在一定程度上改变了输出,因为它(git remote show
)知道它(git remote show
)不知道如果使用该远程名称运行,它(git fetch
或git push
)会做什么。
原子数
但是,我认为没有-n
git remote show
存在相当大的问题。 假设您克隆了一个高度活跃的存储库(例如 Git 或 Linux 内核的 Git 存储库)。 你很好奇git fetch origin
可能会带来什么,如果你现在运行它,所以你运行:
git remote show origin
你的 Git 在 GitHub 或kernel.org
或任何地方调用另一个 Git,与其他软件进行了相当长的对话,最终溢出了一些统计数据。 这需要几秒钟,然后你也会阅读这些相同的统计数据几秒钟——或者你可能在午休后回来阅读它们,或者其他什么。
然后你决定啊,我想要_____(在这里填写一些空白),所以你跑git fetch origin ______
...你得到的东西与git show
展示给你的东西非常不同,因为在你看你会得到什么和你实际跑git fetch
得到东西之间的漫长延迟中,一切都变了。
这并不意味着先看的行为一定是坏的。 例如,它适用于高度不活跃的存储库。 只是不能保证反映未来的现实。 如果你想知道会发生什么,你必须做这件事——不管它是什么——然后看看发生了什么。 在 Git 的情况下,这意味着运行git fetch
.
这种事情是我不喜欢git pull
的众多原因之一。 使用git pull
,您运行git fetch
然后不查看发生了什么,您假设您期望发生的事情确实发生了,然后运行第二个 Git 命令,git merge
或git rebase
。 第二个命令适用于所发生的情况。 它不符合您的期望,除非您很幸运并得到了您所期望的。
如果您对要从中获取并<第二个命令>的存储库了解很多,那么这是合理的。 但是如果你知道的不多,而不是使用git show
然后git pull
,我个人更喜欢运行git fetch
,然后看看我得到了什么,然后才运行第二个命令(或不运行)。 但这确实会因一个 Git 存储库而异(也基于我使用它以来的时间)。第二个命令>
这里的总体思想是原子性。 有些操作,如git fetch
或git push
,是"原子的":它们不能分解为子操作,至少不能从根本上改变事物。 其他操作,如git pull
,可以。 实际上,使用git remote showremote
是试图低于 Git 实际提供的原子性级别。 所以我避免了这一点,只是运行git fetch
,这是 Git 真正原子化的级别。 (另见 https://en.wikipedia.org/wiki/ACID)