如何知道工作目录是指git中的哪个分支? [英] How to know working directory refers to which branch in git?

查看:107
本文介绍了如何知道工作目录是指git中的哪个分支?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据一些研究,我发现git在两个位置保留了两个版本的代码:

According to some researches I figured it out that git keeps two version of the code in two places:

  • .git/refs/heads(本地存储库)
  • .git/refs/remotes/(工作目录)
  • .git/refs/heads (local repository)
  • .git/refs/remotes/ (working directory)

首先,我的理解还可以吗?

First of all, is my understanding ok?

然后,我需要知道headworking directory都指的是哪个分支.有两个命令:

Then I need to know both head and working directory are referring to which branch. There are two commands:

  1. cat .git/head

git branch

您能告诉我这两个命令指的是哪一个吗? (在head中的分支还是在working directory中的分支)?

Can you please tell me those two commands refers to which one? (either the branch that is in the head or the branch that is in the working directory) ?

当您运行git status时,会将您的更改与headworking directory中的版本进行比较吗?

And when you run git status, will your changes be compared with the version which is in the head or working directory?

推荐答案

不,您的理解不正确:.git/refs/中的实体是引用,而不是工作树.

No, your understanding is not OK: the entities in .git/refs/ are references, not work-trees.

(恐怕这会持续很长时间,因为您的问题有点没有重点.)

(I'm afraid this is going to long since your question is kind of unfocused.)

Git过去经常将术语工作目录与术语工作树工作树交替使用.由于与工作目录的操作系统定义相混淆,这种情况在几年前开始改变,您在cd path处运行pwd并在其中打印您的工作目录.我会坚持使用 work-tree .

Git used to use the term working directory interchangeably with the term work-tree or working tree. This began to change a few years ago due to confusing with the operating-system definition of working directory, where you cd path and run pwd to print your working directory. I will stick with the term work-tree.

默认情况下,Git存储库随附一(1)个工作树.该工作树与包含存储库的.git子目录位于同一目录中,因此,如果您具有.git目录,则位于该特定Git工作树的顶层.

A Git repository comes, by default, with one (1) work-tree. The work-tree is located in the same directory as the .git sub-directory that contains the repository, so if you have a .git directory you are in the top level of this particular Git work-tree.

Git存储库的主要功能(至少就Git本身而言)是保存 commits .提交是某些文件集的完整快照.据说保存在提交中的文件是 version ,然后使用git checkout commit-specifier提取提交,会将提交中所有文件的特定版本提取到工作树中.以这种方式存储在提交中的文件被称为版本控制.您已检出的提交(从存储库中提取到工作树中)是当前提交.

The primary function of a Git repository (at least as far as Git itself is concerned) is to hold commits. A commit is a complete snapshot of some set of files. The files stored in the commit are said to be versioned, and using git checkout commit-specifier to extract a commit extracts that particular version of all of the files that are in the commit, into the work-tree. Files that are stored in commits in this way are said to be version-controlled. The commit that you have checked out—extracted from the repository, into the work-tree—is the current commit.

请注意,提交中存储的文件采用特殊的压缩(通常是高度压缩)只读格式.它们不能被更改.一旦Git将某些内容存储为Git格式的对象 1 到存储库数据库中,该内容就不能更改.可以复制它(将其提取为文本格式,以某种方式进行处理,然后将其存储为新的不同版本),但是每个Git对象都通过其表观随机的哈希ID进行记录,该哈希ID实际上是其数据的加密校验和.通过更改内部Git对象的某些内容并再次存储它,您只需创建一个 new 对象,并使用一个新的且不同的哈希ID. 2

Note that files stored in commits are in a special, compressed (often highly compressed), read-only format. They cannot be changed. Once Git stores something as a Git-format object1 inside the repository database, that thing can never be changed. It can be copied—extracted into text format, manipulated in some way, and then stored as a new and different version—but each Git object is recorded by its apparently-random hash ID, which is actually a cryptographic checksum of its data. By changing something about an internal Git object and storing it again, you simply create a new object, with a new and different hash ID.2

Git允许工作树包含不受版本控制的其他文件.在Git的术语中,这些文件是 untracked ;通过逻辑反转,必须跟踪版本控制的文件.也可以忽略(未被忽略的文件).

Git allows the work-tree to contain additional files that are not version-controlled. Such files are untracked, in Git's terminology; by logical inversion, version-controlled files must be tracked. Files that are untracked can also be ignored (files that are tracked cannot be ignored).

Git存储库还带有一(1)个 index . Git的索引是一个关键数据结构,在将Git与工作树一起使用时,您必须始终了解它.该索引是如此重要,或者起初名称不正确,以至于它有两个附加名称:它也称为 staging area ,有时也称为 cache .它最初被称为索引的原因是,在内部它对工作树进行索引(或缓存).不过,这对索引来说对您来说不是很重要.

A Git repository also comes with one (1) index. Git's index is a key data structure that you must be aware of at all times when using Git with a work-tree. This index is so important, or so badly named originally, that it has two additional names: it is also called the staging area, and sometimes the cache. The reason it was originally called the index is that, internally, it indexes (or caches) the work-tree. That's not the important-to-you aspect of the index, though.

索引对 you 的主要作用是保存每个文件的版本.也就是说,当您将当前提交提取到工作树中时,Git真正要做的第一件事就是将提交中的每个文件复制到索引中. (由于索引将文件以相同的压缩格式(仅Git格式)保存,并且在这种情况下实际上 shares 底层Git对象,因此该副本非常快且轻巧."索引,Git可以并且确实将其提取到工作树中,并将其扩展为正常格式,以便非Git程序以及您自己可以查看和/或修改它.

The main thing the index does for you is to hold a version of each file. That is, when you extracted the current commit into the work-tree, the first thing Git really did was to copy each file from the commit, into the index. (This copy is ridiculously fast and light-weight since the index holds the files in the same compressed, Git-only format and in this case actually shares the underlying Git object.) Once the file is in the index, Git can and does extract it into the work-tree, expanding it out to its normal format, so that non-Git programs—and you yourself—can view and/or modify it.

文件的索引副本与同一文件的当前提交副本之间的主要区别在于,索引版本 可以被覆盖.另外,文件在 in 索引中的事实是Git决定文件被跟踪的方式.这为我们提供了跟踪文件的真实定义:仅当索引中存在文件时,才对文件进行跟踪. 3

The key difference between the index copy of a file, and the current commit's copy of that same file, is that the index version can be overwritten. In addition, the fact that the file is in the index is how Git decides that the file is tracked. This gives us the true definition of a tracked file: a file is tracked if and only if it exists in the index.3

Git有许多不同的名称,称为 head:.有 branch heads ,我认为更恰当的称呼是 branch name ,但是Git使用这两个术语可以互换使用,并且有一个特殊的显着的HEAD,应在所有大写字母中键入以下内容.它实际上存储在名为.git/HEAD的文件中. (单个)HEAD始终是当前提交的符号名称. .git/refs/heads/中的项目包括(但不一定是全部)分支名称,而.git/refs/remotes/中的项目包括(但不一定是全部)Git所说的,分别是远程跟踪分支名称远程跟踪分支以及其他一些误导性术语.我更喜欢称这些远程跟踪名称.稍后我们将对此进行更多介绍,但是现在,请记住,这些都是Git称为 reference 的实例.

Git has multiple different things called head: there are branch heads, which are I think more properly just called branch names but Git uses the terms interchangeably, and there is a special distinguished HEAD, which should be typed in all-capitals like this. It is actually stored in a file named .git/HEAD. The (single) HEAD is always a symbolic name for the current commit. Items in .git/refs/heads/ include (but are not necessarily all of) the branch names, and items in .git/refs/remotes/ include (but are not necessarily all of) what Git calls, variously, remote-tracking branch names, remote-tracking branches, and several other misleading terms. I prefer to call these remote-tracking names. We'll have a bit more on this in a moment, but for now, remember that each of these is an instance of what Git calls a reference.

1 Git在主存储库数据库中具有四种类型的对象: commit tree blob ,和带注释的标签.除了 commit 此处,您通常不需要关心任何事情.数据库本身只是一个键值存储,键是哈希ID,值是对象的数据.每当Git通过其键提取对象时,它都可以(并且确实)检测对象损坏,因为数据 的密码哈希必须与键匹配.

1Git has four types of objects in the main repository database: commit, tree, blob, and annotated tag. You normally don't need to care about anything but commit here. The database itself is simply a key-value store, with the keys being the hash IDs and the values being the object's data. Git can (and does) detect object corruption whenever it extract an object by its key, because the cryptographic hash of the data must match the key.

2 请注意,每个提交都有自己独特的,唯一的哈希ID.对于文件而言,情况并非如此:如果文件的内容在多次提交中相同,则该文件在Git中的内部对象在所有这些提交中均具有 same 哈希ID.这是因为哈希ID是 contents 的哈希.每个提交在某种程度上都是唯一的-例如,它们都带有时间戳,因此只要您的计算机时钟有效并且您每秒进行的提交不超过一个,则每个提交都具有唯一的时间戳.实际上,有两个 时间戳,一个用于作者"时间戳,一个用于提交者"时间戳,但是我们不必为此担心.

2Note that each commit has its own distinct, unique hash ID. This is not true of files: if a file's content is the same in multiple commits, that file's internal object inside Git has the same hash ID in all of those commits. This is because the hash ID is the hash of the contents. Every commit is unique in some way—they all have time stamps, for instance, so as long as your computer's clock works and you don't make more than one commit per second, every commit has a unique time stamp. Actually, there are two time stamps, one for "author" and one for "committer", but we need not worry about this yet.

3 当您运行git commit时,Git使用当时索引/登台区域中的任何内容进行 new 提交 .由于索引中的文件已经是仅Git格式的文件,因此提交速度非常快.在具有成千上万个文件的大型项目中,重新压缩每个跟踪的工作树文件会花费太长时间(有时是几秒钟),但是使用索引中已压缩的数据仅需要几毫秒.这是为什么为什么索引存在;并且考虑到该索引存在并且git commit只是将其打包,这就是为什么在索引中存在文件 的原因,这是使文件受到跟踪的原因.

3When you run git commit, Git makes the new commit using whatever is in the index / staging-area at that moment. Because the files in the index are already in the Git-only format, this makes committing very fast. In a large project with tens of thousands of files, re-compressing every tracked work-tree file takes far too long (sometimes many seconds), but using the already-compressed data from the index takes only a few milliseconds. This is why the index exists; and given that the index exists and git commit simply packages it up, this is why the presence of a file in the index is what makes the file tracked.

正如我们刚刚看到的,分支名称是一种特殊的引用. Git引用恰好包含一(1)个哈希ID.分支名称,远程跟踪名称和所有其他类型的引用(标记名称,git replace中的替换条目,等等)都是如此.

As we just saw, a branch name is a specific kind of reference. A Git reference contains exactly one (1) hash ID. This is true of branch names, remote-tracking names, and all other kinds of references (tag names, replacement entries from git replace, and so on).

分支名称只是其全名以refs/heads/开头的引用.这是为什么.git/refs/heads中找到其中一些原因的原因.但是,分支名称​​预期区分大小写:分支xyzzy与分支Xyzzy不同,分支XyzzyxyZZy不同,依此类推.在折叠情况下的Windows和MacOS系统中,当前可以部分解决此问题,但是有时引用存储在文件(.git/packed-refs)中,然后在Windows和MacOS上也可以使用. 4 将来,引用将可能存储在真实数据库中(与存储库对象数据库相邻),这会使它们区分大小写,并且无法通过在.git/refs/heads/中四处查找来找到它们.

Branch names are simply references whose full name starts with refs/heads/. This is why some of them are found in .git/refs/heads. However, branch names are intended to be case-sensitive: the branch xyzzy is different from the branch Xyzzy which is different from xyZZy, and so on. This is currently partially broken in Windows and MacOS systems that fold case, but sometimes references are stored in a file (.git/packed-refs) and then it works on Windows and MacOS.4 In the future, references are likely to be stored in a real database (adjacent to the repository object database) which will make them case-sensitive and make it impossible to find them by poking around in .git/refs/heads/.

远程跟踪名称是其全名以refs/remotes/开头的引用.它们的名称继续包含一个以上的元素,通常为origin/.您的Git使用远程跟踪名称来记住您的Git在其他一些Git存储库中找到的分支名称及其对应的单个哈希ID.虽然它们实际上是您的您的名称,您可以随意更改它们的名称,但是最好只是让您的Git自动更新它们以匹配存储在其他Git中的分支名称.

Remote-tracking names are references whose full name starts with refs/remotes/. Their name goes on to include one more element, typically origin/. Your Git uses remote-tracking names to remember branch names, and their single corresponding hash ID, that your Git found in some other Git repository. While they are in fact your names, and you are free to change them however you like, it's best to just let your Git update them automatically to match the branch names stored in that other Git.

请注意,Git通常会剥离refs/whatever/部分,以便将全名为refs/heads/master的分支名称简称为master.这对下一步至关重要.

Note that Git typically strips off the refs/whatever/ part, so that a branch name whose full name is refs/heads/master is just referred-to as master. This is crucial in the next step.

按照Git的术语,您可以位于分支上 或具有分离的HEAD .当您运行git checkout branchname时,Git将从其哈希ID存储在分支名称​​ branchname 中的提交中填充索引和工作树.它还将分支名称​​复制到 HEAD中,从而使.git/HEAD包含文字字符串ref: refs/heads/branchname.此时,Git将声明您在该分支上.另一方面,如果运行git checkout hash-id,则Git将从您提供的哈希ID的提交中填充索引和工作树(这必须是有效的现有提交),然后将哈希ID本身写入.git/HEAD .此时,Git会声称您有一个分离的HEAD.

In Git's terminology, you can either be on a branch or have a detached HEAD. When you run git checkout branchname, Git populates the index and work-tree from the commit whose hash ID is stored in the branch name branchname. It also copies that branch name into HEAD, so that .git/HEAD contains the literal string ref: refs/heads/branchname. At this point Git will claim that you are on that branch. On the other hand, if you run git checkout hash-id, Git populates the index and work-tree from the commit whose hash ID you gave—this needs to be a valid, existing commit—and then writes the hash ID itself into .git/HEAD. At this point Git will claim that you have a detached HEAD.

因此,如果您的HEAD文件包含原始哈希ID(已分离),则Git可以读取.git/HEAD以获取当前提交的哈希ID.如果您的HEAD已连接,Git可以读取.git/HEAD以获得分支名称,然后读取分支名称-分支名称可以存储也可以不存储在.git/refs/heads/name中,但是肯定存储在某个地方-获取当前的提交哈希ID.无论哪种方式,Git都可以使用您的HEAD查找当前提交.

Hence, if your HEAD file contains a raw hash ID—is detached—Git can read .git/HEAD to get the current commit's hash ID. If your HEAD is attached, Git can read .git/HEAD to get the branch name, and then read the branch name—which may or may not be stored in .git/refs/heads/name, but is definitely stored somewhere—to get the current commit hash ID. Either way, Git can use your HEAD to find the current commit.

每次提交 new 提交时,Git:

Whenever you make a new commit, Git:

  • 创建提交对象. Git本质上冻结了索引中的所有文件版本以用作快照.它使用这些文件(您是作者和提交者)并以现在"作为时间戳构建这些文件的新提交.它使用您的提交消息作为提交日志.而且,至关重要的是,它使用当前提交ID 作为新提交的提交.

现在,提交已经存在并且具有自己的唯一哈希ID,如果已附加HEAD,Git会更新当前分支.也就是说,如果.git/HEAD中具有分支名称,则Git将使用新的分支名称覆盖分支名称的存储的哈希ID.如果您的HEAD已分离,则Git会使用新的哈希ID覆盖.git/HEAD.无论哪种方式,HEAD都继续命名当前提交,因为新的提交现在是当前提交.

Now that the commit exists and has its own unique hash ID, Git updates the current branch, if your HEAD is attached. That is, if .git/HEAD has a branch name in it, Git overwrites the branch name's stored hash ID with the new one. If your HEAD is detached, Git overwrites .git/HEAD with the new hash ID. Either way, HEAD continues to name the current commit, because the new commit is now the current commit.

请注意,因为新提交完全包含了索引/登台区域中的那些文件,所以一旦提交,索引和HEAD提交便会匹配,就像您第一次运行git checkout进行检查时所做的一样删除上一个提交. 工作树根本没有输入这张图片!

Note that because the new commit contains exactly those files that were in the index / staging-area, once you commit, the index and the HEAD commit match, just as they did when you first ran git checkout to check out the previous commit. The work-tree does not enter this picture at all!

4 例如,由于Windows和MacOS不能有两个不同的名为MASTERmaster的文件,因此,仅在大小写不同的情况下使分支名称不同是不明智的.出于同样的原因,提交包含名称仅在大小写不同的文件的提交是一个坏主意,例如,在较早的Linux内核中就是如此.当您签出这样的提交时,索引/暂存区会同时获得两个文件,例如README.TXTreadme.txt,但是您的工作树只能容纳其中的一个,它也变得难以与Git一起使用.

4Because Windows and MacOS cannot have two different files named MASTER and master, for instance, it's unwise to make branch names that differ only in case. For the same reason, it's a bad idea to have commits containing files whose name differs only in case—as was true in older Linux kernels, for instance. When you check out such a commit, your index / staging-area gets both files, e.g., README.TXT and readme.txt, but your work-tree can only hold one of them and it becomes too difficult to work with Git.

然后我需要知道head和work目录都在指哪个分支.

Then I need to know both head and working directory are referring to which branch.

有两个命令:

  1. cat .git/head
  2. git branch
  1. cat .git/head
  2. git branch

如上所述,文件.git/HEAD包含分支名称(如果已连接HEAD)或原始提交哈希(如果已分离HEAD).因此,cat .git/HEAD(您应该使用所有大写字母,以便它可以在其他系统上使用),如果您在分支上,它将告诉您所在的分支.

As I mentioned above, the file .git/HEAD contains either the branch name (if your HEAD is attached) or a raw commit hash (if your HEAD is detached). So cat .git/HEAD—you should use all uppercase so that this will work on other systems—will tell you which branch you are on, if you are on a branch.

默认情况下,git branch命令列出您的分支名称-所有.git/refs/heads/文件以及存储在其他位置的所有分支名称-并在.git/HEAD中的前缀之前添加前缀*.在树枝上.如果您有分离的HEAD,则git branch将在其输出中包括字符串* HEAD detached at ...* HEAD detach from ....确切的细节从一个版本的Git到另一个版本都不同.

The git branch command by default lists your branch names—all your .git/refs/heads/ files plus any branch names that are stored elsewhere—and adds a prefix * in front of the one that is in .git/HEAD if you are on a branch. If you have a detached HEAD, git branch will include in its output listing the string * HEAD detached at ... or * HEAD detach from .... The precise details vary from one version of Git to another.

还有其他一些旨在编写使用Git的代码的命令:git symbolic-ref将读取连接HEAD的分支名称,并打印它,或者如果HEAD被分离则失败.和git rev-parse --symbolic-full-name HEAD将打印全名,例如refs/heads/master(如果您在分支上),或者仅打印HEAD(如果HEAD已分离).使用git rev-parse --abbrev-ref HEAD可以获取分支的简称(refs/heads/被剥离),如果HEAD被分离,则可以再次输入HEAD.

There are several more commands aimed at writing code that uses Git: git symbolic-ref will read the branch name to which HEAD is attached, and print it, or simply fail if HEAD is detached; and git rev-parse --symbolic-full-name HEAD will print the full name, e.g., refs/heads/master, if you are on a branch, or just print HEAD if HEAD is detached. Using git rev-parse --abbrev-ref HEAD you can get the short name of the branch (refs/heads/ stripped), or again HEAD if HEAD is detached.

当您运行git status时,会将您的更改与主目录或工作目录中的版本进行比较吗?

And when you run git status, will your changes be compared with the version which is in the head or working directory?

此特定问题无法按照提出的方式回答. git status的作用是进行两个比较-或多或少两个git diff --name-status es:

This particular question cannot be answered the way it was asked. What git status does is to run two comparisons—two git diff --name-statuses, more or less:

  • HEAD提交和索引之间有什么不同?
  • 索引和工作树之间有什么不同?

第一个差异的结果是 进行提交的更改-如果您现在使用当前索引进行提交,则新快照将与旧快照不同.第二个差异的结果是 not 暂不进行提交的更改.您可以使用git add在索引文件上复制工作树文件,以使索引版本与工作树版本匹配.

The results of the first diff are changes that are staged for commit—if you commit now, using the current index, the new snapshot will differ from the old one. The results of the second diff are changes that are not staged for commit. You can use git add to copy the work-tree files over the index ones, so that the index version matches the work-tree version.

请记住,索引中的内容实际上是建议的提交.更新每个文件的索引/暂存区副本会更改您打算下一步提交的内容.

Remember, whatever is in the index is, in effect, the proposed commit. Updating the index / staging-area copies of each file changes what you are proposing to commit next.

这篇关于如何知道工作目录是指git中的哪个分支?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆