我正在使用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 分支。)
我知道有两个选项可以做到这一点:
因此,了解如何做到这两点会很棒。
我已经阅读了几十个SO答案(包括this,但是似乎每个答案都不同,而且我无法理解这一点。我认为问题是当我使用命令行时,我在本地克隆上而不是在远程上执行某些操作,这与Web界面不同。
顺便说一句,网络界面有两个Pull Request
按钮,每个分支一个。
(在我的情况下,哪一个是正确的?)
我目前的状态是:
## 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;,这显然与我的不一样我在这里问。
答案 0 :(得分:2)
我认为问题在于,当我使用命令行时,我在本地克隆上而不是在远程上执行某些操作,这与Web界面不同。
那是对的。
重要的是要记住Git是一个分布式版本控制系统,并且/或者可能通过社会主义冲动 1 -Git doesn&# 39; t相信 1 任何一个Git存储库都优于任何其他Git存储库。特别是,GitHub上带有dev
和master
的存储库的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 fetch
和git push
。它们实际上非常相似;它们只是以传输方向命名,从开始传输的Git中可以看出。您git fetch
将从提交 提交给您,并且git push
会从您提交给他们。
当你进行这种转移时,工作分为两部分:
第二步是事物不对称。
但在任何一种情况下,您都可以先运行git fetch
或git push
。这告诉你的Git(Fred)打电话给另一个Git(Gertie)。你的Git,Fred,然后问Gertie她有什么,或者提供给Gertie送东西。他们交换有关提交哈希ID的信息,并找出谁错过了什么,然后发送对象。这将获得适当的提交 - 以及与文件名和内容相关的任何相关内容 - 根据需要进入Fred或Gertie。
最后,发送者还会发送名称。因此,如果您正在执行git push
,则Fred会向Gertie发送名称,例如dev
或master
,作为请求的一部分:请将您的dev
或master
设置为此哈希ID。根据GitHub设置的规则,决定是否允许git push --force
,这会更改#34;礼貌请求&#34;到&#34;命令&#34;,但是Gertie 可以 仍然说不。
在fetch
方向,情况有所不同。 Gertie向Fred发送了她所有的提交(Fred还没有),以及所有她的分支名称。然后弗雷德接受她的名字 - 她的dev
和她的master
- 并设置他的 origin/dev
和origin/master
。这样,弗雷德就不会打扰弗雷德的dev
(如果有的话),也不会碰到弗雷德的master
。这些远程跟踪名称(以origin/
开头的名称)的含义是:他们只是弗雷德记住弗雷德的方式看到Gertie,Fred最后一次和Gertie谈过。
由于最后一点,如果你让Fred用git push
召唤Gertie,Fred会向Gertie提供一些新的提交,并要求她设置她master
或她{{1}并且她接受,Fred也会更新Fred dev
或origin/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 Raisins,my 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取决于你提交提交的时间等。)