`git reset --hard master`和`git reset --hard origin/master`有什么区别?

9

我在Stackoverflow和其他地方尝试了很多链接,以更好地理解

git reset --hard option

我知道:

  • 如果省略或使用origin,则重置将在origin上最近的提交上完成
  • 如果提供 SHA1 哈希,则会在相应的提交上进行重置。

我不明白以下值的含义:

  1. origin
  2. HEAD
  3. origin/master
  4. origin/branch

所有这些似乎都具有相同的行为,即它们指向master上的最新提交。

请解释上述所有 4 个值选项的重要性。

我还想知道如果我在特定分支上,如何重置到该分支上的最后一次提交? 例如,如果我在v1.2上,origin/v1.2仍然会将我带到master上的最新提交。

2个回答

13

首先你需要理解分支和标签名只是指向哈希值的指针,哈希值代表一个单独的提交,如果说有4个选项行为相同,那么第一个逻辑答案就是它们都指向同一个提交。

  • origin 我不确定这个,但我认为 origin 本身会解析为 origin/HEAD,这取决于你在 GitHub 的设置中选择了“默认分支”,origin/head 将解析为 origin/[default_branch],在你的情况下,我假设它是 master,所以它与 origin/master 的效果相同。

  • HEAD 总是指向当前提交,也就是你正在执行的提交,所以 git reset --hard HEAD 会永久删除所有已跟踪文件和暂存文件的更改,但不会更改提交哈希值。

  • origin/master 是自上次拉取(fetch/pull)以来远程主分支中的最新提交,每次提交到 master 分支后,你的本地 master 会更新,同时你的 origin/master 也会更新,如果有其他人推送到 master 分支,你的仓库将不会意识到这一更新,除非你进行 git fetch 操作,然后你的origin/master 将超过你的 master,甚至可能分叉。
    如果你当前在 master 分支上,并且 masterorigin/master 同步,那么运行 git reset --hard origin/master 将具有相同的效果。

  • origin/branch我不确定它代表什么,因为默认情况下没有origin/branch,所以我猜想您创建了一个名为branch的分支,并且碰巧与您的主分支在同一提交中。要确认,请尝试运行git branch命令查看所有分支,我猜想您会找到一个名为branch的分支。

  • 如果您想以可视化的方式查看所有这些信息,可以尝试运行git log --graph --decorate --all或者更喜欢使用图形工具gitk,如果您已经安装好二进制文件,则可以运行gitk --all命令以相互比较的方式查看所有分支。


    1
    origin 可以通过 gitrevisions(7) 中的 <refname> 条目来解释;它完全展开为 refs/remotes/origin/HEADorigin/master 展开为 refs/remotes/origin/master,同样地,origin/branch 将展开为 refs/remotes/origin/branch(假设,正如你所说,它存在)。 - chepner

    4

    masterHEADorigin/something,也许还有一些标签,为什么不呢,可能都指向同一个提交,但它们绝对不是同一件事。

    origin通常是远程仓库的名称。

    您可以使用git remote -v查看您的远程仓库并配置新的仓库。

    尝试使用-v选项运行它,这样做可能会让您更容易理解。

    remote/somebranch指向远程仓库上某个分支的head。

    origin/master指向originmaster的head。

    它是否与master相同?

    是和否。如果您拉取了您的master分支,在此期间其他人在master上提交并推送到origin,则它们将不同。

    当您执行git fetch origin时,origin/master将具有其他提交(将领先)。

    HEAD就是"当前提交"。将其视为.

    请参阅此问题

    同样,这可能与master相同,但如果您切换到另一个分支或提交或处于rebase过程中,那么它就不同了。

    因此,请在没有其他人使用的新存储库上尝试此操作:

    $ git checkout master
    $ git log -1 --format="%H" HEAD
    123abc
    $ git log -1 --format="%H" origin/master
    123abc
    

    它们是相同的!

    $ git diff origin/master
    

    当然,它们的内容是相同的。
    $ echo "foo" > foo
    $ git add foo
    $ git commit -m "Foo the thingy"
    $ git log -1 --format="%H" HEAD
    321bca
    $ git log -1 --format="%H" origin/master
    123abc
    

    啊,看,现在它们是不同的提交!
    $ git push origin master
    $ git log -1 --format="%H" HEAD
    321bca
    $ git log -1 --format="%H" origin/master
    321bca
    

    现在它们不再不同!我们已经提交了最新的代码,并且它们都指向相同的内容。

    $ git checkout -b newbranch
    $ echo "baz" > baz
    $ git add baz
    $ git commit -m "Baz the thingy with the stuff"
    $ git branch -a
      master
    * new_branch
      origin/master
    $ git log -1 --format="%H"
    789def
    $ git log -1 --format="%H" master
    321bca
    git log -1 --format="%H" origin/master
    321bca
    git log -1 --format="%H" origin/new_branch
    unknown revision or path not in the working tree.
    

    当然不行。我们还没有将new_branch推送到origin,它仅存在于我们的本地机器上。
    git checkout 123abc
    

    我们刚刚检查了旧的master头部123abc。现在它不是任何分支的头部,但我们仍然可以检出它。
    Note: checking out 123abc. You are in 'detached HEAD' state, etc
    $ git checkout -b old_master
    $ git branch -a
      master
    * new_branch
      origin/master
      old_master
    

    现在猜一下它们分别是什么SHA1?

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接