如何将我过时的(远程)开发分支与我的主分支同步?

时间:2018-03-29 14:36:23

标签: git github

我正在使用github并且只有两个分支,一个用于开发( dev )和一个 master 。我最近从master创建了dev分支,但是后来对(远程)master进行了一些推送,并在(local)master中进行了一些非分段更改,因此远程 dev 分支落后于一些提交。 (并且本地 dev 分支仍然不存在,AFAICT。)

我想图形图就是这样的:

        c  (remote) branch 'dev' 
       /         
  a---b---d---e--*  (remote) branch 'master' (refers to commit 'e')
                     (local) branch 'master' (refers to unstaged changes '*') 
                               ^
                               |
                              HEAD (refers to branch 'master')

问题:

如何将我过时的(远程) dev 分支与分支同步?
(并将未分段的更改导入(远程) dev 分支。)

我知道有两个选项可以做到这一点:

  1. 使用github web界面
  2. 从命令行使用git。
  3. 因此,了解如何做到这两点会很棒。

    我已经阅读了几十个SO答案(包括this,但是似乎每个答案都不同,而且我无法理解这一点。我认为问题是当我使用命令行时,我在本地克隆上而不是在远程上执行某些操作,这与Web界面不同。

    顺便说一句,网络界面有两个Pull Request按钮,每个分支一个。 (在我的情况下,哪一个是正确的?)

    enter image description here enter image description here

    我目前的状态是:

    ## I started this with:
    ## git clone https://github.com/nobody/repo.git
    ## I then edited, pushed some files and created 'dev' branch via GH web.
    ## Finally I edited some more files, so now I have:
    
    $ git status
    
    On branch master
    Your branch is up-to-date with 'origin/master'.
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
            modified:   CHANGELOG.md
            modified:   README.md
    
    $ git branch -a
    
    * master
      remotes/origin/HEAD -> origin/master
      remotes/origin/dev
      remotes/origin/master
    

    PS。 出于某种原因,当谷歌搜索我的问题时,我只得到&#34;同步叉子的结果&#34;,这显然与我的不一样我在这里问。

1 个答案:

答案 0 :(得分:2)

  

我认为问题在于,当我使用命令行时,我在本地克隆上而不是在远程上执行某些操作,这与Web界面不同。

那是对的。

重要的是要记住Git是一个分布式版本控制系统,并且/或者可能通过社会主义冲动 1 -Git doesn&# 39; t相信 1 任何一个Git存储库都优于任何其他Git存储库。特别是,GitHub上带有devmaster的存储库的Git应该比你的机器上的你的 Git更好吗?使用具有master的存储库?

请注意,如果您使用&#34; fork a repository&#34;来创建GitHub存储库。 GitHub Web界面上的按钮,您的GitHub存储库本身就是第三个​​存储库的克隆。 GitHub网页界面&#34;拉取请求&#34;按钮用于向维护此第三个​​存储库的任何人提供请求(通过电子邮件和/或Web),以便从GitHub存储库中提交。这一切都变得非常混乱,并且可能有助于命名每个存储库。 2 让我们命名您自己的存储库Fred,并在GitHub Gertie上调用它。

GitHub试图隐藏很多复杂性,但在我看来,这只会让一切变得更加混乱。忽略所有webby按钮,至少在开始时。

下一个关键是要意识到虽然每个单独的存储库都有自己的名称 -Fred但弗雷德master而Gertie有Gertie的master他们共享实际的提交,或者至少是他们拥有的那些提交。 Git通过唯一的哈希ID 标识每个提交 - 这些看起来像0afbf6caa5b16dcfa3074982e5b48e27d452dbbb,尽管只要它仍然是唯一的,你可以将它们缩短到不那么可怕的东西。 3 如果某个特定提交的哈希ID为0afbf6c...,您可能在您的存储库中拥有该ID,在这种情况下您也有提交,或者您没有。

与此同时,这些名字 - 弗雷德的master和格蒂的master - 用于识别一个特定的哈希ID。如果Fred和Gertie都有提交,那么可以都有master标识该哈希ID。但是,如果两个中的一个没有进行提交,则他们无法将该名称指向该提交。存储库必须具有提交,以便名称指向它(存储其ID)!

1 不要把计算机拟人化,他们讨厌这个。

2 只要你没有将它们全部命名为Bruce。 Or is that as long as you do name them all Bruce?

3 问题是,你怎么知道你能走多远? Git有自己的内部代码来解决这个问题,但这并不能帮助我们穷人。

转移提交

有两个操作将提交(以及与它们一起使用的所有其他对象)一个Git存储库转移到另一个。这些是git fetchgit push。它们实际上非常相似;它们只是以传输方向命名,从开始传输的Git中可以看出。您git fetch提交 提交给您,并且git push会从您提交给他们。

当你进行这种转移时,工作分为两部分:

  • 确定要传输的提交(通过大丑陋的哈希ID)。
  • 获取提交的末尾设置一些名称,以便记住大丑陋的哈希ID。

第二步是事物不对称。

但在任何一种情况下,您都可以先运行git fetchgit push。这告诉你的Git(Fred)打电话给另一个Git(Gertie)。你的Git,Fred,然后问Gertie她有什么,或者提供给Gertie送东西。他们交换有关提交哈希ID的信息,并找出谁错过了什么,然后发送对象。这将获得适当的提交 - 以及与文件名和内容相关的任何相关内容 - 根据需要进入Fred或Gertie。

最后,发送者还会发送名称。因此,如果您正在执行git push,则Fred会向Gertie发送名称,例如devmaster,作为请求的一部分:请将您的devmaster设置为此哈希ID。根据GitHub设置的规则,决定是否允许这个操作。如果她拒绝,您可以尝试使用git push --force,这会更改#34;礼貌请求&#34;到&#34;命令&#34;,但是Gertie 可以 仍然说不。

fetch方向,情况有所不同。 Gertie向Fred发送了她所有的提交(Fred还没有),以及所有她的分支名称。然后弗雷德接受她的名字 - 她的dev和她的master - 并设置他的 origin/devorigin/master。这样,弗雷德就不会打扰弗雷德的dev(如果有的话),也不会碰到弗雷德的master。这些远程跟踪名称(以origin/开头的名称)的含义是:他们只是弗雷德记住弗雷德的方式看到Gertie,Fred最后一次和Gertie谈过。

由于最后一点,如果你让Fred用git push召唤Gertie,Fred会向Gertie提供一些新的提交,并要求她设置她master或她{{1}并且她接受,Fred也会更新Fred devorigin/master。这是机会主义更新: Fred知道Gertie接受了提交,所以现在Gertie的名字必须确定Fred建议的具体提交。

将这两个部分放在一起

  

如何将我过时的(远程)开发分支与我的主分支同步?

这意味着您希望Gertie的origin/dev识别图表中标记为dev的提交。

您可以找到标识提交e的任何内容,例如您的姓名e,或您的姓名master,或您的姓名origin/master,如果全部事实上,这些确实会识别提交HEAD。 (您可以使用e找出 git rev-parse name 提交的内容。或者,运行name:请记住这是Git Log with A DOG。事实上,你可能应该创建一个运行git log --all --decorate --oneline --graph的别名git adog。对于Hysterical Raisinsmy alias for this is git lola。)或者,当然,您可以使用原始哈希ID。然后你通常运行:

git log --all --decorate --oneline --graph

冒号左侧的名称或哈希ID是标识您希望确定Gertie的提交的任何内容,并且您要求Gertie设置内容。 右侧上的名称 - 必须是名称 - 是您要求Gertie 设置的名称。您希望她设置她git push origin <thing-that-identifies-e>:dev ,这样就必须出现在右侧。

但是,当你这样做时,Gertie会看到你要求她将她dev从现在的位置移动,识别提交dev,以识别提交c。她会拒绝!此特定移动将导致Gertie完全从提交图中删除提交e,因为她将为提交c提供 no 名称。那种操作 - 失去提交的操作 - 在Git术语中是非快进,并且需要强制推送&#34;。

因此,您真正需要的是:

c

转动礼貌请求(&#34;做这件事会永远失去承诺git push --force origin <thing-that-identifies-e>:dev &#34;)到命令中(&#34;是的,尽管它会丢失{{1 }}&#34;!)。根据GitHub默认使用的Git规则,Gertie会将她c设置为指向提交c,并且将完全丢失提交dev

如果您希望Gertie 保持提交e,尽管让她移动c以便她c识别提交dev,她设置 new 名称指向dev,最好是让她移动她e。如果不是,那么,删除提交是可以的,只要你的意思并知道你正在做什么。请注意,您目前有一个c的名称,但该名称为dev,Gertie表示&#34;好的我已经改变了c&#34 ; 你的 Git-Fred-会相应地更新你的 origin/dev,所以你也会失去提交dev 4

4 通过Git称之为 reflogs ,您实际上至少还要保留30天。像GitHub这样的服务器通常不会保留reflog,所以他们倾向于立即删除无法访问的提交。

附注:您的origin/dev无法指向未分期的任何内容

c

值得记住,工作树中的任何内容都不在Git中,而且您已经上演但尚未< em> commit 不会永久保存。您的分支名称master 必须指向提交。因此,您的本地(local) branch 'master' (refers to unstaged changes '*') 可能不会指向master,而是指master

暂存文件实际上意味着将其复制到Git称之为 index 的内容中,覆盖以前的版本。索引(也称为登台区域,有时也称为缓存)是构建*将写为 next 的内容的位置承诺。然而,在它实际承诺之前,它只是&#34;索引&#34;它没有提交哈希ID。它的可更改提交是只读的,因此完全不可更改 - 因此它没有ID,并且没有分支名称可以保存它尚未提交的提交ID。

(当你进行提交时,它获得的实际提交ID取决于你提交提交的时间等。)