git checkout HEAD和git checkout [英] git checkout HEAD and git checkout

查看:156
本文介绍了git checkout HEAD和git checkout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

发出命令'git fetch'后,我是否需要使用'git checkout origin/master file_xyz'或git checkout HEAD origin/master file_xyz,以使用文件副本更新文件'file_xyz'中的更改来自原籍/主人?我当前的工作分支不同于来源/主管. "git fetch"会同时更新本地存储库和暂存区吗?

After issuing the command 'git fetch', do I need to use 'git checkout origin/master file_xyz' or git checkout HEAD origin/master file_xyz, to update the changes in the file 'file_xyz' with the copy of the file from origin/master? My current working branch is different from origin/master. Will 'git fetch' update both local repository as well as staging area ?

推荐答案

下面的粗体和斜体字是我的,我认为您的意思是您要问的内容,但我还怀疑您不太了解您的意思.在这里.

The boldface and italics below are mine, and I assume you mean what you are asking, but I also suspect that you don't quite understand what you are implying here.

发出命令git fetch之后,我是否需要使用git checkout origin/master file_xyzgit checkout HEAD origin/master file_xyz,用更新文件file_xyz中的 origin/master文件的副本?

After issuing the command git fetch, do I need to use git checkout origin/master file_xyz or git checkout HEAD origin/master file_xyz, to update the changes in the file file_xyz with the copy of the file from origin/master?

尽管第一个是最接近的,但这两个都不对.您可能想使用git merge,但是此操作在 commit 级别,而不是 file 级别.

Neither of these is right, though the first one is closest. You probably want to use git merge, but this operates at the commit level, not the file level.

我当前的工作分支不同于origin/master. git fetch会同时更新本地存储库和暂存区吗?

My current working branch is different from origin/master. Will git fetch update both local repository as well as staging area?

不.此外,您真的不希望它更新在Git所称呼的任何条目,各种索引,索引范围,临时区域或目录. cache (取决于Git的谁或哪个部分正在执行所说的调用). git fetch的工作是调用其他一些Git,并从该Git下载,无论您拥有什么,而您没有这些承诺.下载了这些提交后(现在也有了它们),您自己的Git会更新您的远程跟踪名称(例如origin/master),以记住哪些提交分支名称,例如 master.请参阅下面的分支说明.

No. Moreover, you really don't want it to update any entries in what Git calls, various, the index, the staging area, or the cache (depending on who or what part of Git is doing said calling). The job that git fetch has is to call up some other Git, and download from that Git, whatever commits they have that you don't. Having downloaded those commits—so that now you have them too—your own Git will update your remote-tracking names, such as origin/master, to remember which commits their branch names, such as their master, identified. See the description of branch below.

您的问题开始于询问某些文件中的更改.值得强调的是(尽可能多!)Git 不存储更改. Git存储快照.如果您随时间拍摄多个快照,并比较两个快照,则可以找出发生了什么变化.这就像是发现差异"难题之一之一,这里的主要认识是您必须拍摄两个 快照才能发现差异.一个快照只是一个快照:没有更改.

Your question starts out by asking about changes in some file. It's worth emphasizing (as many times as it takes!) that Git does not store changes. Git stores snapshots. If you take several snapshots over time, and compare two snapshots, you can find out what changed. This is like one of those "spot the difference" puzzles, and the key realization here is that you must take two snapshots to find some difference. One snapshot is just a snapshot: there are no changes.

Git中的 branch 这个词是模棱两可的,或者至少是人们使用它的方式.它可以引用名称(例如master),也可以引用一个特定的提交(例如32a38237f30759f18b72d069aebd81bbde47bbec(如果这是master的提示)),甚至到最后一次提交的所有一系列 提交.参见分支"到底是什么意思?通常人们已经很清楚了什么意思,但是什么时候没有,找出来是个好主意:它们是指名称提示提交,还是从提示提交中可以到达的部分或全部提交?

The word branch in Git is ambiguous, or at least, it is the way people use it. It can refer to the name, such as master, or to one specific commit (such as 32a38237f30759f18b72d069aebd81bbde47bbec if that's the tip of master), or even to a whole series of commits ending with that last commit. See What exactly do we mean by "branch"? It's usually clear enough what someone means, but when it isn't, it's a good idea to find out: did they mean the name, the tip commit, or some or all commits reachable from the tip commit?

您说过我当前的工作分支不同于origin/master ,如果用工作分支"表示您的分支 name 表示git status报告说:

On branch develop
Your branch is ...

例如

.这是因为您不能在任何远程跟踪名称上使用:诸如origin/master之类的远程跟踪名称实际上并不是分支名称,并且git checkout不会将您置于远程"名称上这样的名字.相反,您最终将处于Git所谓的分离式HEAD"模式(我将不在这里介绍).

for instance. That's because you cannot be "on" any remote-tracking name: remote-tracking names, such as origin/master, are not actually branch names, and git checkout won't put you "on" such a name. Instead, you will end up in what Git calls "detached HEAD" mode (which I won't go into here).

如果您上(如果git status将对某些 B On branch B),则名称为 B 标识一个特定的提交,而该提交就是您的当前提交.该可能是origin/master所标识的同一提交,在git fetch之前和/或之后.或者,可能是一些不同的提交.

If you are on a branch—if git status will say On branch B for some B—then the name B identifies one particular commit, and that commit is your current commit. This could be the same commit that origin/master identifies, before and/or after git fetch. Or, it could be some different commit.

Git中的 commit 是一个唯一的实体,通过其哈希ID进行标识和访问.哈希ID是一个很大的丑陋的字母和数字字符串,例如32a38237f30759f18b72d069aebd81bbde47bbec,它看起来是完全随机的(尽管它是非常 随机的:它实际上是密码内容的加密校验和)犯罪).每个提交都有其自己的,不同的,唯一的哈希ID.如果两个不同的Git存储库都具有具有相同哈希ID的提交,则它们包含 same 提交.这就是您的Git知道的,当您调用另一个Git时,是否需要下载一些提交:另一个Git说,例如,我已经提交了32a38237f30759f18b72d069aebd81bbde47bbec ,然后您的Git检查并说:好,给我不,我已经有了那个.

A commit in Git is a unique entity, identified—and accessed—by its hash ID. The hash ID is a big ugly string of letters and digits, such as 32a38237f30759f18b72d069aebd81bbde47bbec, that appears to be completely random (though it's very much not random: it's actually a cryptographic checksum of the contents of the commit). Every commit has its own, different, unique hash ID. Two different Git repositories contain the same commit if they both have a commit with the same hash ID. That's how your Git knows, when you have it call up the other Git, whether it needs to download some commit: the other Git says, e.g., I have commit 32a38237f30759f18b72d069aebd81bbde47bbec and your Git checks and either says: OK, give it to me or Nah, I already have that one.

这些哈希ID对人类几乎没有用,因此,我们为特定的提交给自己名称.这就是分支名称的来源:它们的Git调用最新的主分支提交master. 他们的名称master标识了他们的最新提交.该提交可能在您的存储库中,也可能不在.您运行git fetch,您的Git调用他们的Git,您的Git找出其哈希ID是什么,并且您的Git 获取必要时进行提交.现在您已经拥有了它,现在您的Git更新了您的origin/master以便记住:他们的Git最后说他们的master是提交__(填写空白)__.

These hash IDs are pretty much useless to humans, and as a result, we give ourselves names for specific commits. This is where the branch names come in: their Git calls their latest master-branch commit master. Their name master identifies their latest commit. This commit might be in your repository, or it might not be. You run git fetch, your Git calls up their Git, your Git finds out what their hash ID is, and your Git gets the commit if necessary. Now you definitely have it, and now your Git updates your origin/master to remember: Their Git last said that their master was commit __(fill in the blank)__.

每个提交都存储所有文件的完整完整快照.这些是特殊的,压缩的,冻结的,仅Git的形式.因为它们是冻结的,所以Git可以在一系列提交中共享,只要它们与先前的提交没有变化即可.您不能更改Git中任何冻结实体的任何部分,包括提交.每个提交还存储一些元数据,例如创建者,创建时间和原因(日志消息).

Every commit stores a full, complete snapshot of all files. These are in a special, compressed, frozen, Git-only form. Because they're frozen, Git can share the files in a series of commits, whenever they are unchanged from the previous commits. You cannot change any part of any frozen entity in Git—including commits. Each commit also stores some metadata, such as who made it, when, and why (the log message).

提交还存储其 parent 或先前提交的哈希ID.这使Git可以从末尾开始-在分支中的 last 提交-并向后工作:

Commits also store the hash ID of their parent, or previous, commit. This allows Git to start at the end—at the last commit in a branch—and work backwards:

... <-F <-G <-H   <--last

分支名称(例如last)保存我们称为H的提交的实际哈希ID.这样,Git就可以找到提交本身.提交包含其父G的哈希ID,这使Git可以找到G. G保留其父级F的哈希ID,依此类推.

The branch name—such as last—holds the actual hash ID of the commit we'll call H. That lets Git find the commit itself. The commit holds the hash ID of its parent G, which lets Git find G. G holds the hash ID of its parent F, and so on.

最终,这就是分支在Git中的工作方式和工作方式. 名称标识 last 提交,其余提交则通过向后工作来找到.

This is, ultimately, how and why branches work the way they do in Git. The name identifies the last commit, and the rest of the commits are found by working backwards.

提交中的文件被冻结且仅支持Git,这对于归档很好,但对完成工作没有用.因此,Git必须有一种方法可以从提交中提取文件,并将其提取到可以进行处理的区域.该区域是工作树.

Files inside commits are frozen and Git-only, which is fine for archiving but useless for getting work done. So Git has to have a way to extract files from commits, into an area where you can work on and with them. That area is the work-tree.

这将足够好:您在可以使用它的工作树中拥有保存在提交中的每个文件的当前冻结副本,以及每个文件的工作副本.您可以告诉Git:从我的工作树中进行新提交,Git会重新压缩每个文件,将其与当前压缩的文件进行比较,然后查看是否需要保存新副本或可以重用旧副本.当它最终完成每个文件的压缩后,就可以进行新的提交了.这将是有效的,但是很慢–例如,对于Linus Torvalds来说太慢了.因此,这并不是Git所做的.

This would be good enough: you have a current frozen copy of each file, saved in a commit, and a working copy of each file, in your work-tree where you can use it. You could tell Git: Make a new commit from my work-tree and Git would re-compress every file, compare it to the current compressed one, and see if it needs to save a new copy or can re-use the old copy. When it finally finished compressing every file, it would be ready to make the new commit. This would be effective, but slow—too slow for Linus Torvalds, for instance. So that's not quite what Git does.

相反,Git会保留每个文件的 1/3 副本.第三份副本已经压缩,可以进入 next 提交了.但是与 current 提交中的副本不同,它不是很冻结.它只是准备冻结.如果您对工作树中的文件的可用副本进行了某些操作,则可以运行git add filename将工作树副本复制回就绪"副本.现在,该文件已暂存为提交.请注意,它已经早于,只是之前的副本与当前冻结的提交中的(仍)副本相同. git add进程只是用新的更新版本覆盖它.

Instead, Git keeps a third copy of every file. The third copy is already compressed and ready to go into the next commit. But unlike the copy in the current commit, it's not quite frozen. It's just ready to freeze. If you've done something to the usable copy of the file in your work-tree, you can run git add filename to copy the work-tree copy back into the "ready to go" copy. That file is now staged for commit. Note that it was already there before, it's just that the copy that was there before is the same as the copy that is (still) in the current, frozen commit. The git add process just overwrite it with the new updated one.

该区域保存了Git提取并提交到工作树中的提交中的所有文件,并准备进入 next 提交(换句话说,就是分阶段提交), index 登台区域缓存,具体取决于Git的调用者是谁或哪个部分.因此,索引/暂存区的目的是记住下一次提交的内容.

This area, which holds all the files from the commit that Git extracted and put into your work-tree and are ready to go into the next commit—staged, in other words—is variously called the index, the staging area, or the cache, depending on who or which part of Git is doing the calling. Hence the intent of the index / staging area is to remember what goes into the next commit.

在某些时候,您可能在工作树中使用了file_xyz并对其进行了某些处理.您现在可能想要保存该内容,以备将来参考.例如,您可以将其与提交之前 中的版本进行比较,以查看您所做的更改.您需要拍摄两个快照(新提交的父级快照和新提交的快照),然后将它们进行比较并找出差异.

At some point you probably took file_xyz in your work-tree and did something with it. You may now want to save that something for future reference. For instance, you'll be able to compare it to the version in the commit just before that commit, to see what you changed. You take the two snapshots—the parent of your new commit, and your new commit—and compare them and spot the difference.

为此,先运行git add file_xyz,然后运行git commit. commit命令收集您的日志消息(为什么您做了什么),并添加您的姓名和当前时间以及所有内容,保存 current 提交的哈希ID,并做出新的提交:

To do that, you run git add file_xyz, and then git commit. The commit command collects your log message—why you did whatever you did—and adds your name and the current time and all that, saves the hash ID of the current commit, and makes a new commit out of it:

...--F--G--H   <-- [before your new commit]
            \
             I   <-- [your new commit]

记住I 的哈希ID,您的Git现在将该哈希ID写入已签出的分支的 name .如果是master,您现在拥有:

To remember the hash ID of I, your Git now writes that hash ID into the name of the branch you have checked out. If that's master, you now have:

             I   <-- master (HEAD)
            /
...--F--G--H   <-- origin/master

名称HEAD附加到的当前分支,这就是Git知道它应该更新master的方式.这也是git status知道说On branch master的方式.您大概是从origin/master创建了master的-Git提交了 their 作为 their master-因此,您的origin/master仍然记住哈希ID H.

The name HEAD is attached to the current branch, which is how Git knows that it was supposed to update master. That's also how git status knew to say On branch master. You presumably created your master from origin/master—the commit their Git had as their master—so your origin/master still remembers hash ID H.

现在运行git fetch.您的Git调用他们的Git并获取他们的新提交.假设他们有一个这样的:

Now you run git fetch. Your Git calls up their Git and obtains their new commit(s). Let's say they have one such:

             I   <-- master (HEAD)
            /
...--F--G--H--J   <-- origin/master

由于他们的master现在可以标识提交J,所以您的 origin/master现在也可以标识其新提交J.

Since their master now identifies commit J, your origin/master also now identifies their new commit J.

此时,您可以运行:

git merge origin/master

这告诉您的Git:找到常见的起始提交,我从中进行一些更改和提交,并从中进行一些更改和提交.找出我们两者所做的更改,并自动合并它们.

This tells your Git: Find the common starting point commit, the one from which I made some changes and committed, and from which they made some changes and committed. Figure out what changes we both made, and combine them automatically.

因此,您的Git从IJ向后走,发现您俩都从提交H开始.这是合并基础.

So your Git walks backwards from I and from J, and finds that you both started from commit H. This is the merge base.

然后您的Git或多或少地运行:

Your Git then runs, more or less:

git diff --find-renames <hash-of-H> <hash-of-I>   # what we changed
git diff --find-renames <hash-of-H> <hash-of-J>   # what they changed

如果您更改了file_xyz并且没有更改,或者如果更改了但没有更改,则合并更改很容易:Git可以获取您的版本或它们的版本.如果您都更改了文件,则Git会对文件的合并基础版本(来自commit H)进行逐行比较,以针对您的文件和与之相对的文件.然后,它组合两组更改,将组合更改应用于H中的文件,并将其用于合并结果.

If you changed file_xyz and they did not, or if they changed it and you did not, combining the changes is easy: Git can just take your version or their version. If you both changed the file, Git does a line-by-line comparison of the merge base version of the file—from commit H—against yours and against theirs. It then combines the two sets of changes, applies the combined changes to the file from H, and uses that for the merge result.

如果所有文件的所有合并均顺利进行,Git将从结果中重新提交:

If all the combining, for all the files, goes well, Git makes a new commit from the result:

             I--K   <-- master (HEAD)
            /  /
...--F--G--H--J   <-- origin/master

您的名字master现在指向此新提交,它将新的更改和您的更改结合在一起.新提交具有两个父级-提交I(您先前的分支提示)和提交J(其当前分支提示)-并且其内容包括冻结的file_xyz combined 会更改为应用于H(合并基础).

Your name master now points to this new commit, which combines their changes and your changes. The new commit has two parents—commit I, your previous branch tip, and commit J, their current branch tip—and has as its contents, including its frozen file_xyz, the combined changes as applied to H, the merge base.

如果毕竟您想放弃file_xyz的更改,然后只使用他们的然后您建议的第一个命令:

If, after all, you want to throw away your changes to file_xyz and just use theirs, then you want the first command you suggested:

git checkout origin/master file_xyz

这会告诉您的Git:找到origin/master标识的提交.到达该提交并获取冻结的内容.将这些冻结的内容放入我的索引中,以便它们在我的下一次提交中,然后将它们冻结/解压缩到我的工作树中,以便我可以查看和使用它们.您当前的 commit 完全没有变化,但是您的索引和工作树现在包含该文件的版本.

This tells your Git: Find the commit origin/master identifies. Reach into that commit and get the frozen contents. Put those frozen contents into my index, so that they will be in my next commit, and unfreeze / de-compress them into my work-tree so that I can see and use them. Your current commit does not change at all, but your index and work-tree now hold that version of the file.

请注意,如果您想从提交H返回到保存的版本,则可以使用相同的技巧:

Note that this same trick works if you want to go back to the saved version from commit H:

git checkout <hash-of-H> -- file_xyz

由于没有明确的名称提交H,您可能要使用其哈希ID.此处不需要--(我们以前不需要),但是这是一个很好的习惯,因为file_xyz看起来不像分支名称或git checkout选项,但其他名称也可能.如果您有一个名为-f的文件或一个名为master的文件,则--会告诉git checkout您是在命名文件,而不是选项或分支.

Since there is no obvious name for commit H, you probably want to use its hash ID. The -- here is not required—we didn't need it before—but is a good habit to get into, because while file_xyz does not look like a branch name or git checkout option, other names might. If you have a file named -f, or a file named master, the -- tells git checkout that you are naming a file, not an option or branch.

这篇关于git checkout HEAD和git checkout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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