git - 关于git pull的 merge/ rebase 步骤的困惑

标签 git

从Loeliger 2ed的Git版本控制中,关于Git Pull中的合并或重设基步骤:
在pull操作的第二步中,git执行
合并(默认设置)或重新定位操作。
关于git pull中的合并步骤:
在本例中,git将
远程跟踪分支,源/主,进入本地跟踪
分支,master,使用一种称为
快进。
但是git怎么知道要合并那些特定的分支呢?答案
来自配置文件:

[branch "master"]
        remote = origin
        merge = refs/heads/master

这给了git两条关键信息:when master
是当前的已签出分支,使用原点作为默认远程
在获取(或拉取)期间从中获取更新。
此外,在git pull的合并步骤中,使用refs/heads/master
从远程作为默认分支合并到此,主
分支。
一般来说,合并步骤是将远程跟踪分支合并到master还是当前分支?我猜是当前的分支,即HEAD所指的分支,它不一定master
注意我的猜测来自https://git-scm.com/docs/git-pull
将远程存储库中的更改合并到当前
分支。在默认模式下,git pull是git fetch的缩写。
后面是git merge fetch_head。
更准确地说,git pull使用给定的参数运行git fetch并
调用git merge将检索到的分支头合并到当前
分支。
是否总是将远程跟踪分支合并到当前分支?(我猜是的)。
如果不是,是否有git pull的参数指定合并步骤中的目标分支?
如果我是正确的,git pullrefspec参数没有指定合并步骤的目标分支。
为什么合并是“快进合并”?
关于git pull中的rebase步骤:
命令git pull--rebase将导致git重新定位(而不是
合并)本地跟踪分支到远程跟踪分支
只在这次拉的时候。
git pull的重设基址步骤是否将当前分支(即由git pull指向的分支)重设基址到远程跟踪分支?
如果是,为什么报价说“您的本地跟踪分支机构”而不是当前分支机构?

最佳答案

一般来说,合并步骤是将远程跟踪分支合并到主分支还是当前分支?
这两个是相同的:master是您当前的分支。远程跟踪分支是origin/master
(其中origin只是用于远程的默认名称,而不是任何特殊的git“关键字”,并且master是默认分支。实际名称在实际情况下可能会有所不同。)
rebasemerge操作的目标(结果更改将在其中进行)是当前分支。
如果你试图做一些愚蠢的事情,比如试图使跟踪分支成为当前分支,git将与你抗争。
因此,合并的目标是checkout origin/master。问题是,什么会合并?如果你拉一些新的上游材料,你可能会(例如)这种情况:

     YOURS (master)             
             *
              \      UPSTREAM (origin/master)    
                *     *
                 \   /
                   *      <--- "git merge-base master origin/master"
                   |
                   *

mastermaster已发散,分别有2个和1个新提交。
使用origin/mastergit rebase下的两个本地提交在上游的顶部被重写:
      YOURS (master)             
              *       <-- rewritten: SHA changes
               \          
ghost of YOURS  *       <-- rewritten: SHA changes
      * ---- *    \
              \     * UPSTREAM (origin/master)
               \  /
                 *
                |

现在的情况是“本地分支YOURSmaster提前2次提交”。您已准备好(尝试)origin/master
你原来未改写的承诺仍然存在(在ASCII图表中用“你的鬼魂”来表示)。它们在git push中被引用。当它们从那里过期或被手动清除时,它们就变成垃圾,最终被垃圾收集起来。
使用git reflog您可以执行其他操作:您的更改与git merge合并,并创建一个新的提交,该提交有两个父级:
                  * YOURS-merged (master)
                /  \
     YOURS    /      \          
             *        |
              \       |  UPSTREAM (origin/master)    
                *     *
                 \   /
                   *      <--- "git merge-base master origin/master"
                   |
                   *

现在您的origin/mastermaster提前一次提交。如果现在成功地推送,远程存储库的origin/master也将呈现上述形状,两个父级将沿着一条路径提交更改,而上一个上游将沿着另一条路径提交更改。没有“你的鬼魂”:你的改变从来没有被重写过。
为什么合并是“快进合并”?
在两种情况下都会发生快进合并或重新定位。一是master没有任何并行的变化:
     YOURS (master)             
             *
              \          
                *
                 \  
                   *    UPSTREAM (origin/master)
                   |
                   *

在上述情况下,无需执行任何操作:所有操作都是最新的,而且您比origin/master提前两次提交。因此,这不是一个“快速前进的任何东西”;aorigin/mastergit merge将完全不做任何事情。如果您对这些提交感到满意,可以尝试git rebase
真正的快进场景发生在没有任何本地更改的情况下:
                     * UPSTREAM (origin/master) 
                    /
    YOURS (master) *
                   |
                   *

在这种情况下,如果您执行git pushgit rebase,那么默认情况下,您的git mergemaster指针只是“向前滑动”以指向与HEAD相同的提交,并且此幻灯片是“快进”:
        YOURS (master) *  UPSTREAM (origin/master)  
                     /
                    *  <- master slid forward from here
                    |
                    *

“快进”术语可能指的是只有origin/master指针移动(以及要匹配的本地文件系统树的重写)。无需编写或重写新的提交。
在不同的场景中不可能快速前进(除非放弃本地更改)。必须生成一个新的合并提交,或者rebase必须重写一些更改。在这些操作之前,不存在任何可以直接向前滑动的任务。
有些人以某种方式使用git,他们希望本地工作的所有提交都是合并的。当没有新的上游工作可供合并时,您可以使用HEAD(没有快进)强制git进行合并提交。从这个开始:
     YOURS (master)             
             *
              \          
                *
                 \  
                   *    UPSTREAM (origin/master)
                   |
                   *

你会得到这样的东西:
               ----* YOURS-merge   (master)
     YOURS    /    |  
             *     |
              \    |     
                *  |
                 \ | 
                   *    UPSTREAM (origin/master)
                   |
                   *

其思想是,在历史的主线道路上,这两个变化似乎浓缩为一个步骤。可以跟随另一个父级查看多个提交的详细沿袭。
为什么引用的是“你的本地跟踪分支”而不是当前分支?
这是个错误。所有涉及的分支都是本地的(在您的存储库中)。有工作分支(如master)及其远程跟踪分支(如git merge --no-ff)。两者都是本地的。
你工作的分支不称为跟踪分支;它不跟踪任何东西。
一些本地分支没有与远程跟踪分支配对。回购协议中没有远程分支(例如master新创建的分支)的所有分支都是纯本地的。除非推送到远程回购,否则任何本地创建的分支都是纯本地的。
远程跟踪分支是与本地分支配对的类似分支的对象。它能跟踪上游在做什么。每次执行origin/master,它都可能被重写以指向某些不同的提交。本地分支不受影响。两者可能会分道扬镳,这可以通过重新定位或合并来解决。执行git init时,本地分支将更新上游回购中的实际远程分支。当此操作成功(未被远程端拒绝)时,本地跟踪分支也会更新以指向同一提交,因此它们保持同步。
正常情况下,纯本地操作不会改变git fetch:它跟踪远程回购中相应分支的状态。

关于git - 关于git pull的 merge/ rebase 步骤的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34503156/

相关文章:

Xcode:添加 git 服务器: "Server is disabled"

GIT:不止一个开发人员在处理同一个功能

github:没有可用的受支持的身份验证方法

git - 如何让 `git log --name-status` 与 merge 提交一起工作?

git - 从 Git 存储库中提取特定版本文件

svn - 我知道 svn 和 git。如何理解 Perforce?

git 部署项目 - 文件权限 - (chmod)

bash - 如何检查 git merge 是否真的在多 repo bash 脚本中进行了 merge

git - 如何删除 Git 存储库中的多个已删除文件

git - 如何将 Git 浅克隆转换为完整克隆?