Git:将存储库更新为某个版本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17942396/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 16:40:01  来源:igfitidea点击:

Git: update a repository to certain revision

git

提问by Sébastien Dawans

Say I have a repository that has a revision number A. And I would like to update it to revision B, while the latest revision is C. (revision A is earlier than B, and B is earlier than C). I'm new to git so I did some research, and found this, which inspires me a solution:

假设我有一个版本号为 A 的存储库。我想将其更新为版本 B,而最新版本是 C。(版本 A 早于 B,而 B 早于 C)。我是 git 的新手,所以我做了一些研究,发现了这个,这启发了我一个解决方案:

git pull # update from A to the latest revision C
git reset --hard B

That does work. But since I can't git reset --hard Bfrom A directly, the precedent update to latest is still too heavy, I wonder there might be some one-line command to match my need. Any hints please?

那确实有效。但是因为不能git reset --hard B直接从A,先例更新到latest还是太重了,不知道有没有什么单行命令可以满足我的需求。请问有什么提示吗?

回答by Sébastien Dawans

There is no "updating a repository to a certain version". You repository has all the versions, that's what git fetch/ git pulldoes.

没有“将存储库更新到某个版本”。您的存储库拥有所有版本,这就是git fetch/ 的git pull作用。

If you want put a specific revision of the repo in your current working tree locally, there are several ways you could do that. The closest to your questions is:

如果您想在本地将 repo 的特定修订版放入当前的工作树中,有几种方法可以做到这一点。最接近你的问题是:

update your local repository:

更新您的本地存储库:

git fetch origin

create a new branch (from whatever branch you are currently on, we will reset hard later so it doesn't matter):

创建一个新分支(从您当前所在的任何分支开始,我们稍后将对其进行硬重置,因此无关紧要):

git branch yourbranchname
git checkout yourbranchname

The above 2 operations can be abbreviated into one (the current HEAD is assumed as source of the branch):

以上2个操作可以简写为一个(假设当前的HEAD是分支的源头):

git checkout -b yourbranchname

then place the pointer of that branch to the commit you need (B):

然后将该分支的指针指向您需要的提交 ( B):

git reset --hard sha1-of-B

git reset --hard will always work, it doesn't depend on your branch's history, the only condition for it to work is that commit B is in you local object base (i.e. B must exist and must have been fetched from a remote repo is it is not your work).

git reset --hard 将始终有效,它不依赖于您的分支的历史记录,它起作用的唯一条件是提交 B 在您的本地对象库中(即 B 必须存在并且必须从远程仓库中获取是不是你的工作)。

As @Hasturkun points out, you can also branch directly from any arbitrary hash with an extra argument:

正如@Hasturkun 指出的那样,您还可以使用额外的参数直接从任意散列中分支:

git checkout -b yourbranchname SHA-1

回答by jbr

You need to use git checkoutfor this. Just do:

您需要为此使用git checkout。做就是了:

git checkout B

git 结帐 B

and you'll have that revision.

你会得到那个修订版。

回答by cmaster - reinstate monica

Your approach is entirely wrong. You are modifying something that you don't want to modify: Your current branch (presumably master).

你的做法是完全错误的。您正在修改您不想修改的内容:您当前的分支(大概是master)。

A simple, linear git repository is a chain of commits like this

一个简单的线性 git 存储库是一个像这样的提交链

*---A---*---*---B---*---*---C
    ^                       ^
    |                       |
  master              origin/master
    ^
    |
   HEAD

That is the state of your repository after you have called git fetch. Note that the entire history with all its intermediate steps is right there on your local hard drive. It's just that you only have the state at commit Achecked out (HEADpoints to masterwhich points to A), so the files that you see belong to that state.

这是您调用后存储库的状态git fetch。请注意,整个历史及其所有中间步骤都在您的本地硬盘上。只是您只A检查了提交时的状态(HEAD指向master哪个指向A),因此您看到的文件属于该状态。

Now, if you just want to look at the state that was committed as B, you can just check out that commit with git checkout B. This updates the files that you see to the state of B, and points HEADat that commit:

现在,如果您只想查看作为 提交的状态B,您可以使用git checkout B. 这会将您看到的文件更新为B,并指向HEAD该提交:

*---A---*---*---B---*---*---C
    ^           ^           ^
    |           |           |
  master       HEAD   origin/master

HEADalways references the commit/branch that gitthinks you are on, and to which it will compare your work directory when you call git status.

HEAD始终引用git认为您所在的提交/分支,并且在您调用git status.

The simple git checkout Bis sufficient, if you just want to look at that commit. If you actually want to make changes that you commit and want to preserve, you should introduce a new branch to record those changes. This is achieved by a simple git checkout -b newBranchafter the git checkout B. This will give you the state

git checkout B如果您只想查看该提交,那么简单就足够了。如果您确实想要进行您提交并想要保留的更改,您应该引入一个新分支来记录这些更改。这是通过一个简单git checkout -b newBranchgit checkout B. 这会给你状态

*---A---*---*---B---*---*---C
    ^           ^           ^
    |           |           |
  master    newBranch origin/master
                ^
                |
               HEAD

This just gives a name to commit Bother than its hash value. After some more commits, your state would look like this:

这只是给出了一个提交的名称,B而不是它的哈希值。再提交几次后,您的状态将如下所示:

*---A---*---*---B---*---*---C
    ^           |           ^
    |           |           |
  master         \    origin/master
                   \
                    *---*---D
                            ^
                            |
                        newBranch
                            ^
                            |
                           HEAD

The point is, that, after checking out some other branch/commit with git checkout ..., you can always easily return to commit Dby calling git checkout newBranch, and the permanent reference stops gitfrom garbage collecting commit D.

关键是,在使用 检出其他分支/提交后git checkout ...,您始终可以D通过调用轻松返回到提交git checkout newBranch,并且永久引用停止git垃圾收集提交D



Now, why is using git reset --hardbad? First of all, it clobbers all your local changes that you have not committed yet without further notice. Second, it may loose you history if you are not careful with it.

现在,为什么使用git reset --hard不好?首先,它会破坏您尚未提交的所有本地更改,恕不另行通知。其次,如果您不小心,它可能会丢失您的历史记录。

Consider, for example, the case that you have made some changes after you last pushed to your upstream repository, and want to take a look at some historic commit B. (Somewhat the opposite of the case in your question.) The history looks like this:

例如,考虑这样一种情况,您在上次推送到上游存储库后进行了一些更改,并希望查看一些历史提交B。(与您问题中的情况有些相反。)历史看起来像这样:

  *---A---*---*---B---*---*---C
      ^                       ^
      |                       |
origin/master               master
                              ^
                              |
                             HEAD

With git reset --hard B, you get this state:

使用git reset --hard B,您将获得以下状态:

  *---A---*---*---B-(-*---*---C )
      ^           ^
      |           |
origin/master   master
                  ^
                  |
                 HEAD

The commits in parentheses are not referenced directly or indirectly by any branch anymore, and may be garbage collected any time. gitmay not be very aggressive with garbage collecting, but if it does garbage collect while you are in this state, there is no way for you to get commit Cback, it will be lost forever. You don't want this to happen, so it's not a good idea to get into the habit of using git reset --hardlightly.

括号中的提交不再被任何分支直接或间接引用,并且可能随时被垃圾收集。git垃圾收集可能不是很激进,但是如果它在您处于这种状态时进行垃圾收集,则您无法C恢复提交,它将永远丢失。您不希望这种情况发生,因此养成git reset --hard轻率使用的习惯并不是一个好主意。

Had you used git checkoutinstead, the branch masterwould still be pointing at C, and you would still be able to get back to it with a simple git checkout master.

如果您git checkout改用,分支master仍将指向C,并且您仍然可以使用简单的git checkout master.