本文介绍了Git为什么说我的主分支“已经更新"?即使不是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚从项目中的文件中删除了所有代码,并将更改提交到了本地git(故意).我做了

I just deleted ALL the code from a file in my project and committed the change to my local git (on purpose). I did

git pull upstream master

从上游获取并合并(因此从理论上讲,应该返回已删除的代码).

to fetch and merge from upstream (so in theory that deleted code should be back).

Git告诉我一切都是最新的.

Git tells me everything is up to date.

所有内容绝对不是最新的-所有已删除的代码仍将被删除.

Everything is definitely NOT up to date -- all that deleted code is still deleted.

我只有一个分支,称为"master".

I only have one branch called "master".

我最近设置了主人"来跟踪上游,就像这样:

I recently set up "master" to track upstream like so:

命令git branch -vv产生:

* master 7cfcb29 [upstream/master: ahead 9] deletion test

为什么为什么会这样?我即将通过电子邮件将我对代码所做的任何更改发送给我的项目经理.

Why why why is this happening? I'm on the verge of just e-mailing my project manager any changes I make to our code.

我认为这很明显,但是无论如何,这是我的目标:

I thought it was obvious, but anyways this is my goal:

获取我系统上的最新代码.

在这里让我感到愤怒,但是为什么这么简单的任务必须如此艰巨呢?

Excuse my anger here, but why does such a simple task as that have to be so hard?

推荐答案

我认为您的基本问题是您误解和/或误解了git的作用及其原因.

I think your basic issue here is that you're misinterpreting and/or misunderstanding what git does and why it does it.

克隆其他存储库时,git会复制那里"的内容.它还使用其"分支标签(例如master),并复制该标签的副本,该标签在git tree中的全名"(通常)为remotes/origin/master(但在您的情况下,remotes/upstream/master).在大多数情况下,您也可以省略remotes/部分,因此可以将原始副本称为upstream/master.

When you clone some other repository, git makes a copy of whatever is "over there". It also takes "their" branch labels, such as master, and makes a copy of that label whose "full name" in your git tree is (normally) remotes/origin/master (but in your case, remotes/upstream/master). Most of the time you get to omit the remotes/ part too, so you can refer to that original copy as upstream/master.

如果您现在对某些文件进行一些更改并将其提交,则您是唯一拥有这些更改的文件.同时,其他人可能会使用原始存储库(从中创建克隆)来创建其他克隆并更改这些克隆.当然,他们是唯一具有更改的人.最终,有人可能会将更改发送回原始所有者(通过推送"或补丁或其他方式).

If you now make and commit some change(s) to some file(s), you're the only one with those changes. Meanwhile other people may use the original repository (from which you made your clone) to make other clones and change those clones. They are the only ones with their changes, of course. Eventually though, someone may have changes they send back to the original owner (via "push" or patches or whatever).

git pull命令通常只是git fetch的缩写,后跟git merge.这很重要,因为这意味着您需要了解这两个操作的实际作用.

The git pull command is mostly just shorthand for git fetch followed by git merge. This is important because it means you need to understand what those two operations actually do.

git fetch命令说,返回到您从其克隆的任何位置(或已设置为从其获取的位置),并找到其他人添加或更改或删除的新内容".这些更改将被复制并应用于您先前从中获得的内容.他们不是应用于您自己的作品,而仅应用于他们的作品.

The git fetch command says to go back to wherever you cloned from (or have otherwise set up as a place to fetch from) and find "new stuff someone else added or changed or removed". Those changes are copied over and applied to your copy of what you got from them earlier. They are not applied to your own work, only to theirs.

git merge命令更加复杂,您将在其中出错.简单地说,它所做的是将您在副本中所做的更改"与您从其他人那里获取的更改,并因此添加到您的其他人的副本中"进行比较.如果您的更改及其更改似乎没有冲突,则merge操作会将它们混合在一起,并为您提供一个合并提交",将您的开发及其开发联系在一起(尽管有一种非常常见的简单"情况,您没有任何变化,就会获得快速前进".

The git merge command is more complicated and is where you are going awry. What it does, oversimplified a bit, is compare "what you changed in your copy" to "changes you fetched from someone-else and thus got added to your-copy-of-the-someone-else's-work". If your changes and their changes don't seem to conflict, the merge operation mushes them together and gives you a "merge commit" that ties your development and their development together (though there is a very common "easy" case in which you have no changes and you get a "fast forward").

您现在所遇到的情况是您进行了更改并提交了更改(实际上是九次,因此是提前9"),而他们却没有更改过 .因此,fetch尽职尽责地不获取任何内容,然后merge接受他们的零钱并且也不执行任何操作.

The situation you're encountering now is one in which you have made changes and committed them—nine times, in fact, hence the "ahead 9"—and they have made no changes. So, fetch dutifully fetches nothing, and then merge takes their lack-of-changes and also does nothing.

您想要查看的甚至是重置"其版本"的代码.

What you want is to look at, or maybe even "reset" to, "their" version of the code.

如果您只想查看它,只需检查一下该版本即可:

If you merely want to look at it, you can simply check out that version:

git checkout upstream/master

这告诉git您想将当前目录移到全名实际上是remotes/upstream/master的分支.您将在上次运行git fetch并获得其最新代码时看到他们的代码.

That tells git that you want to move the current directory to the branch whose full name is actually remotes/upstream/master. You'll see their code as of the last time you ran git fetch and got their latest code.

如果您想放弃所有自己的更改,您需要做的是更改git的想法,即标签master应该命名的修订版本.当前,它命名您的最新提交.如果您回到该分支:

If you want to abandon all your own changes, what you need to do is change git's idea of which revision your label, master, should name. Currently it names your most recent commit. If you get back onto that branch:

git checkout master

然后,git reset命令将允许您像以前一样移动标签".唯一剩下的问题(假设您真的准备好放弃已做的所有事情)是找到标签应指向的位置.

then the git reset command will allow you to "move the label", as it were. The only remaining problem (assuming you're really ready to abandon everything you've don) is finding where the label should point.

git log将让您找到数字名称(例如7cfcb29之类的数字),它们是永久的(永不更改)名称,并且还有很多其他方式来命名它们,但是在这种情况下,您只需要名称upstream/master.

git log will let you find the numeric names—those things like 7cfcb29—which are permanent (never changing) names, and there are a ridiculous number of other ways to name them, but in this case you just want the name upstream/master.

要移动标签,清除您自己的更改(您所做的任何更改实际上都可以恢复一段时间,但是这样做之后要困难得多,因此请确保非常确信):

To move the label, wiping out your own changes (any that you have committed are actually recoverable for quite a while but it's a lot harder after this so be very sure):

git reset --hard upstream/master

--hard告诉git清除正在执行的操作,移动当前分支标签,然后检出给定的提交.

The --hard tells git to wipe out what you have been doing, move the current branch label, and then check out the given commit.

真的想要git reset --hard并消灭大量工作并不罕见.一种更安全的方法(如果您认为其中有些值得的话,使恢复工作容易得多)是重命名现有分支:

It's not super-common to really want to git reset --hard and wipe out a bunch of work. A safer method (making it a lot easier to recover that work if you decide some of it was worthwhile after all) is to rename your existing branch:

git branch -m master bunchofhacks

然后创建一个名为master的新本地分支,以跟踪"(我不喜欢这个术语,因为我认为它会使人们感到困惑,但这是git术语:-))原始(或上游)主节点:

and then make a new local branch named master that "tracks" (I don't really like this term as I think it confuses people but that's the git term :-) ) the origin (or upstream) master:

git branch -t master upstream/master

然后您就可以开始使用它:

which you can then get yourself on with:

git checkout master

最后三个命令的作用(有一些快捷方式使它仅是两个命令)是更改粘贴在现有标签上的名称,然后创建一个新标签,然后切换到它:

What the last three commands do (there's shortcuts to make it just two commands) is to change the name pasted on the existing label, then make a new label, then switch to it:

在做任何事情之前:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "master"

在git branch -m之后:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

在git branch -t master upstream/master之后:

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

此处C0是您第一次执行git clone时获得的最新提交(完整的源代码树). C1到C9是您的提交.

Here C0 is the latest commit (a complete source tree) that you got when you first did your git clone. C1 through C9 are your commits.

请注意,如果您先按git checkout bunchofhacks,然后按git reset --hard HEAD^^,则会将最后一张图片更改为:

Note that if you were to git checkout bunchofhacks and then git reset --hard HEAD^^, this would change the last picture to:

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 -    "bunchofhacks"
                                                      \
                                                       \- C8 --- C9

原因是HEAD^^将修订版本从当前分支的开头(在重置之前为bunchofhacks)命名为两个,然后reset --hard然后移动标签.提交C8和C9现在几乎是不可见的(您可以使用reflog和git fsck之类的东西来查找它们,但不再琐碎了).您可以随意移动标签. fetch命令负责以remotes/开头的命令.按照惯例,将您的"与他们的"匹配(因此,如果他们也有一个remotes/origin/mauve,您也要为您的mauve命名),但是只要您想命名/查看提交的内容,就可以键入他们的".从他们". (请记住,一次提交"是整个源代码树.如果需要,您可以从一次提交中选择一个特定文件,例如,使用git show.)

The reason is that HEAD^^ names the revision two up from the head of the current branch (which just before the reset would be bunchofhacks), and reset --hard then moves the label. Commits C8 and C9 are now mostly invisible (you can use things like the reflog and git fsck to find them but it's no longer trivial). Your labels are yours to move however you like. The fetch command takes care of the ones that start with remotes/. It's conventional to match "yours" with "theirs" (so if they have a remotes/origin/mauve you'd name yours mauve too), but you can type in "theirs" whenever you want to name/see commits you got "from them". (Remember that "one commit" is an entire source tree. You can pick out one specific file from one commit, with git show for instance, if and when you want that.)

这篇关于Git为什么说我的主分支“已经更新"?即使不是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 17:17
查看更多