Git 命令之 fetch、merge、pull

2020-12-05  本文已影响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 \

结论

这三个命令都可以缺省参数使用,但如果使用参数 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> ...]]

上一篇下一篇

猜你喜欢

热点阅读