美文网首页
Git 命令之 fetch、merge、pull

Git 命令之 fetch、merge、pull

作者: 莫帆海氵 | 来源:发表于2020-12-05 16:33 被阅读0次

    定义

    git fetch

    Download objects and refs from another repository.
    Fetch branches and/or tags (collectively, "refs") from one or more other repositories, along with the objects necessary to complete their histories.
    From git-scm

    从另一个仓库下载对象和引用。
    从一个或多个仓库获取分支或标签,以及完成提交历史所必须的对象。

    # 命令格式
    
    git fetch [<options>] [<repository> [<refspec> <refspec> ...]]
    git fetch <repository> <head>:<master>
    

    example

    # git config remote.<repository>.fetch
    remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
    
    # 基于上面的配置,也是默认的配置执行下面命令
    
    # 1. 不指定具体分支名称时,它会获取 origin 存在的所有分支
    git fetch
    git fetch origin
    
    # 命令格式 fetch <repository>
    # 命令可以缺省 <repository>
    # fetch 可以缺省 origin,那它默认使用的什么【疑问1】
    
    # 执行日志如下
    mac@hgwang2019 ze % git fetch
    From https://gitlab.xxx.com/whg/ze
       d17d36e..0ab3813  feat/c     -> origin/feat/c
    
    
    # 2. 指定具体名称时仅更新名称对应的分支
    git fetch origin master
    git fetch origin master:
    git fetch origin +seen:seen master:main
    
    # 命令格式 <head>:<branch>
    # 命令可以缺省符号右边 <head>:
    # 命令还可以缺省符号 <head>
    # 命令可以指定多个名称 <head1> <head2>
    # + 指不使用快进模式更新,默认块进模式更新
    
    # 执行日志如下
    % git fetch origin master
    From https://gitlab.xxx.com/whg/ze
     * branch            master     -> FETCH_HEAD
     
    % git fetch origin master:
    From https://gitlab.xxx.com/whg/ze
     * branch            master     -> FETCH_HEAD
     
    % git fetch origin master:m1
    remote: Enumerating objects: 1, done.
    remote: Counting objects: 100% (1/1), done.
    remote: Total 5 (delta 1), reused 1 (delta 1), pack-reused 4
    Unpacking objects: 100% (5/5), done.
    From https://gitlab.xxx.com/whg/ze
     * [new branch]      master     -> m1
       7700707..3db84ff  master     -> origin/master
    
    # 3. 错误的列子
    
    git fetch xxx
    
    # repository 随便输入会提示 xxx 不是一个仓库
    
    # 执行日志如下
    % git fetch ttt
    fatal: 'ttt' does not appear to be a git repository
    fatal: Could not read from remote repository.
    
    Please make sure you have the correct access rights
    and the repository exists.
    
    
    

    git merge

    Join two or more development histories together.
    Incorporates changes from the named commits (since the time their histories diverged from the current branch) into the current branch. This command is used by git pull to incorporate changes from another repository and can be used by hand to merge changes from one branch into another.
    From git-scm

    合并两个或更多个开发历史记录到一起。
    将已经提交的记录(自提交历史记录从当前分支分开的时间开始)合并到当前分支。git pull 使用此命令来合并另一个仓库的更改,也可以手动用来合并一个分支到另一个分支

    # 命令格式
    git merge [<options>] [<commit> <commit> ...]
    git merge <branch> <branch>
    
          A---B---C topic
         /
    D---E---F---G master
    
         A---B---C topic
        /         \
    D---E---F---G---H master
    
    # 假如有上面两个分支的提交记录
    # 在 master 分支上执行 git merge topic 后
    # 会把 topic 上从 master 分支分出去后的所有改动都重现到 master 分支上
    # 并在最后追加一个新的提交记录 H
    # 所以执行 merge 命令后通常会多出一条记录
    

    example

    # 1. 默认的命令
    git merge master
    
    # 执行日志如下
    % git merge master
    Updating c33c0e4..3db84ff
    Fast-forward
     c5.js | 1 +
     1 file changed, 1 insertion(+)
     create mode 100644 c5.js
    
    
    # 2. 无参数命令
    git merge
    
    # 日志输出如下
    # 当前分支在 master
    # 从日志看和命令 git merge origin/master 一致
    % git merge
    Already up to date.
    
    # 另一个 merge,已经 fetch 
    % git merge
    Updating ac1a5ba..269f8fd
    Fast-forward
     b7.js | 1 +
     1 file changed, 1 insertion(+)
    
    # 3. 不自动追加新的提交记录
    git merge --no-commit master
    
    
    # 执行日志如下
    # 如果当前分支有比 master 更早的提交记录
    # 当前分支显示需要再次提交合并过来的新文件
    % git merge --no-commit master
    Automatic merge went well; stopped before committing as requested
    % git status
    On branch feat_3
    All conflicts fixed but you are still merging.
      (use "git commit" to conclude merge)
    
    Changes to be committed:
    
        new file:   c7.js
    
    # 如果当前分支没有比 master 更早的提交记录
    % git merge --no-commit master
    Updating 3db84ff..fefc896
    Fast-forward
     c6.js | 1 +
     1 file changed, 1 insertion(+)
     create mode 100644 c6.js
    % git log
    commit fefc8968a648b3da29b3b698a9d0b67f2e2ec429 (HEAD -> feat_3, origin/master, master)
    Merge: 3db84ff 8e7a0c7
    Author: 莫帆 <whg@xxx.com>
    Date:   Fri Sep 18 14:14:58 2020 +0800
    
        Merge branch 'feat/c' into 'master'
        
        Feat/c
        
        See merge request whg/ze!17
    
    commit 8e7a0c76f6dcd952049995523a68c06593c92758 (origin/feat/c)
    Author: 莫帆 <whg@xxx.com>
    Date:   Fri Sep 18 14:14:46 2020 +0800
    
        feat: add c6
    
    
    # 终止合并,在合并中遇到冲突不想解决或者不想在使用当前合并内容
    # 执行后会回滚到 merge 命令之前的状态
    git merge --abort
    
    

    git pull

    Fetch from and integrate with another repository or a local branch.
    Incorporates changes from a remote repository into the current branch. In its default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD.
    From git-scm

    从另一个仓库或本地分支获取然后在合并。
    git pull = git featch + git merge

    git pull fetches from origin by default and merges into the current branch.
    From "Pro Git book"

    # 命令格式
    
    git pull [<options>] [<repository> [<refspec> <refspec> ...]]
    git pull <repository> <branch>
    
    

    example

    # 1. 指定分支名称
    git pull origin feat_3
    
    在远端分支有新的更新后执行该命令都多一条提交记录(不论本地的提交记录,有更前的、更后面的、还是没有)
    
    # 日志输入如下
    # 看日志能分别对应上是分别执行了 git fetch 和 git merge 的
    # 且从 log 上看和 merge 行为一致都会多一条提交记录
    % git pull origin feat_3
    remote: Enumerating objects: 3, done.
    remote: Counting objects: 100% (3/3), done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
    Unpacking objects: 100% (3/3), done.
    From https://gitlab.xxx.com/whg/ze
     * branch            feat_3     -> FETCH_HEAD
       fad7482..901afea  feat_3     -> origin/feat_3
    Merge made by the 'recursive' strategy.
     b6.js | 1 +
     1 file changed, 1 insertion(+)
     create mode 100644 b6.js
    % git log
    commit 1cef28fa5d69727bde66934bc8b0811c8ac44a42 (HEAD -> feat_3)
    Merge: 5296e52 901afea
    Author: 莫帆 <wanghaigang@innotechx.com>
    Date:   Fri Sep 18 15:31:58 2020 +0800
    
        Merge branch 'feat_3' of https://gitlab.xxx.com/whg/ze into feat_3
    
    commit 901afeab4672ccb5f0ebf19ba3a6c378d2e6c81a (origin/feat_3)
    Author: 莫帆 <whg@xxx.com>
    Date:   Fri Sep 18 15:31:46 2020 +0800
    
        feat: add b6
    
    commit 5296e52c21cc07b3cf28f2168c2dc4321eea65b1
    Author: 莫帆 <whg@xxx.com>
    Date:   Fri Sep 18 15:31:25 2020 +0800
    
        feat: change b1 console
    
    # 2. 无参数命令
    git pull
    git pull origin
    
    
    # 日志输出如下
    # 看日志结果是分别执行的 git fetch 和 git merge origin/feat_3
    % git pull
    remote: Enumerating objects: 2, done.
    remote: Counting objects: 100% (2/2), done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 2 (delta 0), reused 2 (delta 0), pack-reused 0
    Unpacking objects: 100% (2/2), done.
    From https://gitlab.xxx.com/whg/ze
       a452809..1e68dd0  master     -> origin/master
    Already up to date.
    
    # 结合 git fetch 的说明,第一步和执行缺省参数的 git fetch 一致
    # 第二步执行 git merge,但它是如何知道 merge origin/feat_3 分支的【疑问2】
    
    

    branch.<name>.remote 和 branch.<name>.merge

    Defines, together with branch.<name>.remote, the upstream branch for the given branch. It tells git fetch/git pull/git rebase which branch to merge and can also affect git push (see push.default). When in branch <name>, it tells git fetch the default refspec to be marked for merging in FETCH_HEAD. The value is handled like the remote part of a refspec, and must match a ref which is fetched from the remote given by "branch.<name>.remote".
    The merge information is used by git pull to lookup the default branch for merging \

    • branch.<name>.remote 用于定义 <name> 分支对应远端分支的 repository,这里一般默认为 origin
    • branch.<name>.merge 设置的值定义 fetch、pull 默认合并哪个分支
    • 假如在 <name> 分支执行 git merge,相当于执行 git merge origin/<name>
    • 同样在 <name> 分支执行 git pull,相当于 git pull origin <name>
    • 这里就解释了【疑问1】【疑问2】中的问题

    结论

    这三个命令都可以缺省参数使用,但如果使用参数 pull、fetch 和 merge 有差异,前者需要指定 repository,后者只需要分支名称即可。

    // 这里 repository 就是默认值 origin
    git fetch origin master
    git pull origin master
    
    // 这里不需要 respository,分支名称指定远端的 master 分支
    git merge origin/master
    

    附上命令的定义

    git fetch [<options>] [<repository> [<refspec> <refspec> ...]]
    git merge [<options>] [<commit> <commit> ...]
    git pull [<options>] [<repository> [<refspec> <refspec> ...]]
    
    

    相关文章

      网友评论

          本文标题:Git 命令之 fetch、merge、pull

          本文链接:https://www.haomeiwen.com/subject/ygugwktx.html