12

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

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

这确实有效。但是由于我不能git reset --hard B直接从A,所以先更新到最新的还是太重了,我想知道可能有一些单行命令来满足我的需要。请问有什么提示吗?

4

3 回答 3

20

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

如果您想在本地当前工作树中放置特定版本的 repo,您​​可以通过多种方式做到这一点。最接近您的问题的是:

更新您的本地存储库:

git fetch origin

创建一个新分支(从您当前所在的任何分支,我们稍后会重新设置,所以没关系):

git branch yourbranchname
git checkout yourbranchname

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

git checkout -b yourbranchname

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

git reset --hard sha1-of-B

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

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

git checkout -b yourbranchname SHA-1
于 2013-07-30T09:00:00.260 回答
5

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

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

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

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

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

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

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

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

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

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

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

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


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

例如,假设您在上次推送到上游存储库后进行了一些更改,并希望查看一些历史提交B。(与您的问题中的情况有些相反。)历史如下所示:

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

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

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

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

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

于 2017-02-24T09:16:24.613 回答
4

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

git结帐B

你会有那个版本。

于 2013-07-30T08:57:47.350 回答