origin/main 和 origin/HEAD 在我的提交中意味着什么,为什么它们是红色的?
我已经开始使用 Git,最近学会了使用它
git log --all --graph
来查看我的提交历史记录,我注意到一些令人担忧的细节。例如,左边的线是红色的,这表明有问题。此外,在提交名称之后有一些我无法解释的文本。我认为 HEAD -> main
表示 HEAD 指向 main。但是还有另外 2 个字符串(也是红色表示有问题),我认为它们是遥控器?
左边的线是否表明有问题,或者我读错了?提交编号旁边的文本是什么意思?这三个部分分别代表什么意思呢?有什么问题吗?如果有,我该如何修复?
这是我日志中的最上面一行。 origin/main
和 origin/HEAD
是什么意思?为什么它们是红色的?
* commit 9bee2dac5bb71b843022409d33a46af52be217d4 (HEAD -> main, origin/main, origin/HEAD)
I've started using Git, and I've recently learned to use
git log --all --graph
to look at my commit history, and I noticed some details that I find worrying. For example, the line to the left is red, which indicates to me that something is wrong. Moreover just after the name of the commit there is some text which I have trouble interpreting. I think that HEAD -> main
means that the HEAD is pointing to main. But then there are 2 more strings (also in red indicating something is wrong) which I think are remotes?
Is the line to the left indicating something is wrong, or am I reading it wrong? What does the text next to the commit number mean? What do the three parts mean? Is there something wrong, and if so how can I fix it?
This is the topmost line in my log. What does origin/main
and origin/HEAD
mean and why are they red?
* commit 9bee2dac5bb71b843022409d33a46af52be217d4 (HEAD -> main, origin/main, origin/HEAD)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Git 实际上就是关于提交。提交具有哈希 ID:
那个
9bee...7d4
东西是您在main
分支上最新提交的哈希 ID。随着您和其他人添加新的提交, 最新的提交会随着时间的推移而发生变化,但目前,9bee2da...
是最新的。如果 Git 没有更简单的方法来命名提交,那么所有使用 Git 的人都会发疯。 (有人说 Git 无论如何都会这样做。)想象一下必须记住这些又大又难看的随机数 -寻找东西只是为了得到你的承诺!但您不必这样做:Git 会将每个分支的最新提交的哈希 ID 保存在分支名称中。
那么,存储库主要由两个数据库组成:一个(通常是最大的)保存提交并支持内部 Git 对象。这些都有哈希 ID;您将处理提交的哈希 ID。为了帮助您和 Git 本身找到提交和其他哈希 ID,存储库还存储了一堆名称:分支名称、标签名称、refs/ stash 代表。对。其中一些名称是分支名称,这些名称是存储库中的分支。
git stash
,等等。这个大名称表中的每个名称都存储一个哈希 ID,这是存储库中的另一个数据库:一组(对象数据库中的对象是完全只读的:一旦提交,您就永远无法更改它。名称中的名称数据库存储哈希 ID,但存储的哈希 ID 可以随时替换,甚至可以删除和/或创建新名称,因此名称会随着时间的推移而变化,以选择最新。 em> 提交。我们将跳过所有其余的细节。 不过,
Git 不仅仅是一个版本控制系统 (VCS):它是一个分布式 VCS。 Git 通过让我们复制存储库来实现这种分发技巧。我们使用 git clone 来做到这一点。当我们克隆其他人的 Git 存储库时,我们会获取他们的所有提交1,并且没有获得他们的任何分支。他们提交的哈希 ID 就是此时我们提交的哈希 ID:任何一个提交的哈希 ID 对于该特定提交都是完全唯一的 em>,以及每个具有 that 提交的 Git 存储库,都使用 that 哈希 ID。该哈希 ID 现在为该提交保留。 (这就是为什么它们又大又丑的原因:这样,总有一个新的 ID 可用于您的所有新提交。)
记住它们的分支名称,我们的 Git 在我们的克隆中创建或更新我们自己的远程跟踪名称。我们的 Git 软件会记住我们用于制作克隆的 URL,使用更短的(比 URL)名称。这里有一个标准的名字,
origin
,每个人都使用它,2,因此他们的 Git 存储库的 URL 存储在名称下起源
。然后,Git 使用该相同名称粘贴在每个分支名称前面:它们的main
成为我们的origin/main,他们的
develop
(如果他们有的话)成为我们的origin/develop
,等等。因此,您的
origin/*
名称只是反映了您克隆的存储库具有一些分支名称这一事实。他们的分支名称 = 您的远程跟踪名称,因为您的 Git 会看到它们的名称并更改它们,以便让您的存储库记住它们的分支。因为您和他们共享提交——您的所有提交都来自他们——他们的
origin/main
会记住提交哈希 ID9bee2da。 ..
。一旦您的 git clone 操作复制了它们的提交并修改了它们的分支名称,您自己的 Git 软件就会在您的存储库中创建一个新分支。您的 Git 此处使用的名称是main
。3 因此您的 Git 创建了您自己的main
来匹配您的origin/main
> 你的 Git 用它来记住它们的main
。这意味着您拥有:
main
:这是您的(目前)提交9bee2da...
的名称;origin/main
:这是您的他们分支名称的副本,上次您的Git与他们的Git软件对话和存储库,名为 commit9bee2da...
。因此,当您运行
git log
时,您的 Git:main
查找9bee2da...
;9bee2da...
查找提交;9bee2da...
;(实际上,第 1 步之前还有一个步骤:您的 Git 使用
HEAD
来查找main
。但我们暂时不考虑该部分。)1我们可以获得少于所有提交,但是“复制所有提交”至少是首先考虑这个问题的方法。
2如果您愿意,您可以使用其他东西。如果这样做,您的远程跟踪名称将会有所不同。但其他人都会期望看到
起源
,因此没有必要做额外的工作来使用不同的名称。3您在
git clone
时告诉您的 Git,您希望 Git 复制哪个分支名称。例如,要选择他们的develop
,您可以运行git clone -bdevelopment...
。如果您不选择分支名称,您的 Git 会询问他们推荐的 Git 名称,通常是他们的 main 或 master 或其他名称。绿色和红色,但没有什么问题
否:Git 默认只使用八种颜色,即
red
、green
、blue
、yellow
、青色
、洋红色
、黑色
和白色
。这就是 20 年前常见的一切。这里允许使用一些额外的单词,如果您的终端支持,现代 Git 可以使用 24 位颜色(请参阅 Git 漂亮格式颜色< /a>)。对于画线部分(参见漂亮的 Git 分支图),Git 以红色开头(并且没有简单的方法来配置这)。这是正确的:特殊名称
HEAD
(实际上不是分支名称)通常包含某个分支的名称;当它发生时,我们说名称HEAD
附加到,或指向该分支名称。这些是我上面提到的远程跟踪名称。 git Branch -a 将显示分支名称(始终是本地的,因此“本地分支”是多余的,就像说“ATM 机”,但有时无论如何感觉都合适)和远程跟踪名称;它默认以绿色打印分支名称,默认以红色打印远程跟踪名称。我不确定这是否是一种助记设备(“红色=远程”),但如果您愿意,您可以将其用作助记设备。 (但是绿色等于什么?“Glocal”听起来太像“global”了。
Git is really all about commits. The commits have hash IDs:
That
9bee...7d4
thing there is the hash ID for your latest commit on yourmain
branch. The commit that is the latest will change over time, as you and others add new commits, but for now,9bee2da...
is the latest.If Git didn't have easier ways to name commits, this would drive all the humans working with Git insane. (Some say that Git does that anyway.) Imagine having to memorize these big ugly random-looking things just to get your commits! But you don't have to do that: Git will save the hash ID of the latest commit of each of your branches, in a branch name.
Repositories, then, consist primarily of two databases: one—usually the biggest—holds the commits and supporting internal Git objects. These all have hash IDs; the commits' hash IDs are the ones you will deal with. To help you—and Git itself—find the commit and other hash IDs, the repository also stores a bunch of names: branch names, tag names,
refs/stash
forgit stash
, and so on. Each name in this big table of names stores one hash ID, and that's the other database in a repository: a set of <name, hash-ID> pairs. Some of these names are branch names, and those are the branches in the repository.(The objects in the objects database are fully read-only: once you make a commit you can never change it. The names in the names database store hash IDs, but the stored hash IDs can be replaced at any time, or even deleted and/or new names created. So the names change over time, to select the latest commit. We'll skip all the rest of the details here, though they do matter.)
Git isn't just a version control system (VCS) though: it's a distributed VCS. Git does this distribution trick by letting us copy a repository. We use
git clone
to do that. When we clone someone else's Git repository, we get all their commits1 and none of their branches. The hash IDs of their commits are the hash IDs of our commits at this point: the hash ID of any one commit is totally unique to that particular commit, and every Git repository that has that commit, uses that hash ID for it. That hash ID is now reserved for that commit. (This is why they're so big and ugly: that way, that there's always a fresh new ID available for all of your new commits.)To remember their branch names, our Git, in our clone, creates or updates our own remote-tracking names. Our Git software remembers the URL we used to make the clone, using a shorter (than a URL) name. There's a standard first name here,
origin
, which everybody uses,2 so the URL for their Git repository is stored under the nameorigin
. Git then uses that same name to stick in front of each of their branch names: theirmain
becomes ourorigin/main
, theirdevelop
(if they have one) becomes ourorigin/develop
, and so on.So your
origin/*
names are simply a reflection of the fact that the repository you cloned has some branch names. Their branch names = your remote-tracking names, because your Git sees their names and changes them, to let your repository remember their branches.Because you and they share the commits—you got all your commits from them—their
origin/main
remembers commit hash ID9bee2da...
. Once yourgit clone
operation has copied their commits and modified their branch names, your own Git software creates one new branch in your repository. The name your Git used here wasmain
.3 So your Git created your ownmain
to match yourorigin/main
that your Git uses to remember theirmain
.That means you have:
main
: this is your name for (at the moment) commit9bee2da...
;origin/main
: this is your copy of their branch name that, the last time your Git talked with their Git software and repository, named commit9bee2da...
.So when you run
git log
, your Git:main
to find9bee2da...
;9bee2da...
to find the commit;9bee2da...
;(There's actually a step before step 1: your Git uses
HEAD
to findmain
. But we're leaving that part out for now.)1We can get less than all commits, but "copy all commits" is the way to think about this at first, at least.
2You can use something else if you want. If you do, your remote-tracking names will be a little different. But everyone else will expect to see
origin
, so there is no point to doing extra work to use a different name.3You tell your Git, at
git clone
time, which of their branch names you want your Git to copy. To select theirdevelop
, for instance, you'd rungit clone -b develop ...
. If you don't pick a branch name, your Git asks their Git which name they recommend, and usually that's their main or master or whatever.Green and red, but nothing wrong
No: Git just uses eight colors by default, namely
red
,green
,blue
,yellow
,cyan
,magenta
,black
, andwhite
. This is all that was commonly available 20 years ago. There are some additional words allowed here, and modern Git can use 24-bit color if it's supported by your terminal (see Git pretty format colors). For the line-drawing part (see Pretty Git branch graphs), Git starts with red (and there's no easy way to configure this).That's correct: the special name
HEAD
—which is not actually a branch name—normally holds the name of some branch; when it does, we say that the nameHEAD
is attached to, or points to that branch name.These are the remote-tracking names I mentioned above.
git branch -a
will show both branch names (which are always local, so "local branch" is redundant, like saying "ATM machine", but sometimes it feels appropriate anyway) and remote-tracking names; it prints the branch names in green by default, and the remote-tracking names in red by default. I'm not sure if this is meant as a mnemonic device ("red = remote"), but you can use it as one, if you like. (But then what does green equal? "Glocal" sounds way too much like "global". ????)The second red name is
origin/HEAD
: this is your Git's copy of the other Git'sHEAD
, more or less. However, Git doesn't update it, the way it updates remote-tracking names.4 If you think theirHEAD
may have changed, you can rungit remote set-head origin --auto
to have your Git call up their Git and find where theirHEAD
is now. But there's very little use fororigin/HEAD
in my opinion, so I never bother.4Every time you run
git fetch origin
, your Git calls up their Git again, using the URL Git saved under the nameorigin
, and picks up any new commits they have, that you don't, and updates your remote-tracking names based on their branch names. In fact,git clone
is really just shorthand for runninggit init
+git remote add origin ...
+git fetch origin
+ a few more steps: it's thegit fetch
step that creates all your remote-tracking names initially, and gets all their commits initially. Sincegit fetch
defaults to get the commits they have that I don't, and initially you have no commits, it initially gets all their commits. Since it doesn't create or update any branch names—only remote-tracking names—that's whygit clone
copies all their commits and none of their branches.