【问题标题】:Why do git reset & push use slashes vs spaces between remote and branchname?为什么 git reset 和 push 在远程名称和分支名称之间使用斜杠和空格?
【发布时间】:2016-12-11 23:29:06
【问题描述】:

git reset is often used after a force push 或强制更新以复制分支的所有远程更改。例如,在使用

进行变基和强制推送之后
git push --force origin my_branch

您的团队成员可以使用

git reset --hard origin/my_branch

获取更新的分支。问题是为什么必须为git reset 指定斜线/,而不是git push

【问题讨论】:

    标签: git github version-control


    【解决方案1】:

    这更像是一个长评论,而不是一个正确的答案。

    我想这个问题的一般答案是这样的:

    “它是这样编程的”

    更严肃地说,这可能与资源及其位置有关。我这里所说的资源是localremote

    让我们看看您在原始帖子中提到的两个命令。

    git push -f <remote> <branch>

    那么 push 实际上是做什么的呢?简而言之,它会将您在本地存储库中的任何内容推送到上游到远程存储库。我们将如何做到这一点?从设计的角度来看,如果您考虑一下,在这种情况下传递两个参数是非常有意义的.

    接下来,我们来看看

    git reset --hard <remote>/<branch>

    这条指令基本上会将你的工作目录重置为你指定的index。另外,请注意这一切都是从您的local file system 完成的,这是您在 OP 中提出的两个命令之间的区别。

    【讨论】:

    • 事实上,这是正确的答案:git push 的最后一个参数不是分支名称,而是一个 refspec,在这种情况下是一个 pair 分支名称:存储库中的某种提交说明符,然后是冒号,然后是 their(来源)存储库中您想要 them的名称> 改变。另一方面,git reset 的最后一个参数只是任何合适的提交说明符。分支名称(像foo 这样的常规本地分支,或像origin/foo 这样的远程跟踪分支)作为提交说明符可以正常工作,但像a1234567 这样的哈希也是如此。 (续)
    • 另一方面,git pushrefspec 参数的最后部分 必须 是名称,而不是原始提交哈希。另外,这是他们的名字,而不是你的!因此它永远不是origin/foogit push refspecs 的有趣之处在于,如果您使用自己的名称,则可以省略 their 名称(和冒号)。确切的细节有所不同,但通常这意味着“双方同名”。也就是说,foo:foo 可以缩短为 foo
    • @torek 你介意对我上面的回答进行适当的修改,以反映你刚刚在评论部分所说的话。我完全同意它和它在技术上的更好定义。或者,如果您不介意,我可以自行整合适当的更改并征得您的同意
    • 我会把它留给你。 :-)
    【解决方案2】:

    git push 命令首先采用remote 参数,您可以在其中指定要推送到的存储库,然后是本地分支引用以更新相应的远程分支。

    但是,

    git reset 采用单个 path 参数,您可以在其中指定远程 repo 的分支(通过路径)以将本地副本重置为。

    要直接回答您的问题,git reset 需要斜杠的原因是因为它采用一个路径参数,而不是采用两个单独参数的 git push:远程和分支。

    您不妨参考git pushgit reset Git 官方文档。

    【讨论】:

      【解决方案3】:

      为什么是 / ?

      git push <remote> <branch> 中,您提供了两个参数:远程名称和分支名称。因此没有理由添加/remote 是这里必不可少的部分;毕竟push会和它通信。

      git reset ... origin/my_branch 中,您提供一个 参数:分支的名称。在这种情况下,origin/my_branch 分支的名称,完全指定。您还可以在此处给出本地分支的名称(在这种情况下,您将省略 .../ 部分。因此,如果两者之间有空格(而不是使用完全限定的分支名称),它会变得非常混乱和容易出错。reset 不关心甚至不知道遥控器。

      小心

      git reset --hard origin/my_branch

      这首先需要git checkout my_branch,否则您将重置您当前所在的任何其他分支。您可能需要编辑您的问题,以免偶然发现它的人产生错误印象。

      保留他们的更改

      更重要的是,在强制推送变基后,无需进行硬重置(即丢弃分支上所有本地提交的更改)。您的同事可以简单地对他们进行相同 rebase 操作,然后一切都恢复正常(当然,不是在有很多很多冲突的病理情况下)。 “rerere 缓存”可以在这里提供帮助(请参阅 git help rerere)。

      所以,如果做了:

      git checkout my_branch
      git rebase abc12345
      git push --force
      

      然后他们可以这样做:

      git fetch   # in case they do not have abc12345 yet
      git checkout my_branch
      git rebase abc12345
      git pull
      

      rebase 操作是可重复的,所以通常情况下应该可以正常工作。这将让其他开发人员保留他们所有的本地更改并让您的更改居于首位(请记住,pull 基本上是merge)。

      【讨论】:

      • 删除然后重新创建分支(git branch -D my_branch 后跟git checkout my_branch)的坏处在于这会丢弃您对my_branch 的引用日志。好吧,那,而且,不小心使用了错误的名称(对于没有上游的私有分支)可能会更糟。 :-)
      • 我也喜欢git branch -f 方法,除了另一个问题:如果您当时确实那个分支上,它会在不改变索引的情况下移动标签和工作树。如果您之前有一个干净的索引和工作树,这会给您留下很多“要提交的更改”。 (然后你可以用git reset --hard 修复它,但你需要知道检查并理解为什么会发生这种情况。)它确实表明没有必要离开当前分支,如果上游变基你需要处理影响了一些 other 分支。
      • 呸,你完全正确。我已经删除了我的答案的那部分,如果不遇到困难就很难做到正确;无论如何,这不是重要的部分。 ;)
      猜你喜欢
      • 2011-02-01
      • 1970-01-01
      • 2015-08-15
      • 2021-09-01
      • 2014-10-17
      • 2022-06-17
      • 2023-04-10
      相关资源
      最近更新 更多