新手问题 git pull 和 git fetch 有什么区别?

chairy11 · 2013年11月22日 · 最后由 echoocking 回复于 2018年07月18日 · 95202 次阅读

话说,git pull 和 git fetch 有什么区别?好迷糊……

题外话: 之前看了两遍 codeschool 的 GIT REAL 和 GIT REAL2,有点晕。 又看了本《Git Pro》,感觉清晰了点。 一到用,又忘光光了……

pull = fetch + merge

git pull = git fetch + merge to local

#1 楼 @nouse #2 楼 @dddd1919 额,那我现在在 develop branch 上,我 git pull 了,而 origin 上的更新也是在 develop 上,到底出现了啥子结果? 是不是如果不是 master 上,就应该用 fetch?

关于不带参数执行 git pull git push 的行为,可以参考之前写的 http://loveky2012.blogspot.com/2012/08/default-behaviour-of-git-pull-and-git-push.html 需翻墙

#4 楼 @nightire 先谢谢……辛苦了,这么长的答案……

不过……呐……看了没天,其实……不太懂……😓

是不是用 git pull,就会直接把 origin/X 分支的东东 merge 到我的本地 X 分支?都自动对应的。 origin/X的改动绝对不会放到我的本地Y分支下?

不过我朋友刚对我说“在冲突不多的情况下直接 pull 更省事,很多人合作的话省下来的事有点得不偿失,不过我们现在没这个问题。而且你也没有 merge 其他 branch 的需求,直接 pull 吧。 除非你有明确的目标,否则不用手动去 merge,否则出问题的可能更大”

我最服 @nightire 有才有德,程序员的典范

#5 楼 @loveky 谢谢,呐,字好密集,读不进了……下次下次……

#7 楼 @Peter 在一起,在一起!哈哈哈哈哈哈

#9 楼 @chairy11 别人对你那么好,我就不参和了,不过话说回来, @nightire 无论对谁都是超有耐心,细心打一堆字。

再我喜欢 Tab 不喜欢空格,说不定就这一点就不能做朋友了~~~

#10 楼 @Peter 我是说,你们好基友,在一起啊在一起…… 好基友不会在乎空格滴……

区别就是,只用git fetch就可以了

#12 楼 @bhuztez 。。。为嘛跟我的结论刚好相反?以上各位及我小伙伴给我的启示是:git pull 对我来说最省事也最不容易出错的……

@chairy11 我只记住了 pull = fetch + merge……其实建个 repo 自己测试一下就可以了 XD

刚学 git 的时候每次我都 fetch + merge,后来就用 git pull 了(因为太懒)

如果搞不清楚的话,老老实实git pull [remote] [branch] 是最稳当的。出了问题 git 也会给 log,很舒服。

#13 楼 @chairy11 你是只有一个分支吧

#15 楼 @bhuztez 我用 git flow,有一个 master, 一个 develop 和很多 feature. 两至三个人……

大爱 git fetch

#6 楼 @chairy11 既然文字太多不喜欢看,就一步一步来吧

# git init --bare parent.git    # 创建一个bare repo用做clone用,相当于server端repo
Initialized empty Git repository in /home/gewang/test/test/parent.git/

# git clone parent.git child1 # clone出第一个工作repo
Cloning into 'child1'...
done.
warning: You appear to have cloned an empty repository.
# cd child1/
# echo a > a && git add . && git commit -m "init drop" # 第一次commit
[master (root-commit) 985c04f] init drop
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 a

# git push origin master:master # 在server端repo中创建master分支
Counting objects: 3, done.
Writing objects: 100% (3/3), 206 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/gewang/test/test/parent.git
 * [new branch]      master -> master

# cd ..
# git clone parent.git child2 # 创建第二个工作repo
Cloning into 'child2'...
done.
# cd child2/
# git checkout -b test # 创建test分支
Switched to a new branch 'test'
# echo abc >> abc && git add . && git commit -m "create test branch"
[test c3d70fd] create test branch
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 abc

# git push origin test:test # 将test分支推送至服务器,注意没有加-u参数
Counting objects: 4, done.
Delta compression using up to 24 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 268 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/gewang/test/test/parent.git
 * [new branch]      test -> test

# git config -l # 查看配置,由于没有使用-u参数,所以没有test分支对应的remote, merge配置项
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=/home/gewang/test/test/parent.git
branch.master.remote=origin
branch.master.merge=refs/heads/master


# cd ../child1 # 回到第一个工作repo
# git branch
* master
# git pull origin test # 在master分支上执行 git pull origin test, 可以看到server端test分支的内容被merge进了本地master分支
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/gewang/test/test/parent
 * branch            test       -> FETCH_HEAD
Updating 985c04f..c3d70fd
Fast-forward
 abc |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 abc

# git fetch # 执行git fetch为server端test分支建立本地镜像分支
From /home/gewang/test/test/parent
 * [new branch]      test       -> origin/test
# git branch -a
* master
  remotes/origin/master
  remotes/origin/test

# git checkout test # 虽然本地没有手工创建test分支,但是可以直接checkout,同时git自动为你配置了它与server端test分支的关联。够贴心。
Branch test set up to track remote branch test from origin.
Switched to a new branch 'test'
# git config -l
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=/home/gewang/test/test/parent.git
branch.master.remote=origin
branch.master.merge=refs/heads/master
branch.test.remote=origin
branch.test.merge=refs/heads/test

# echo ddd >> ddd && git add . & git commit -m "update branch test" # 在test分支上checkin代码并推送至服务器
[1] 1260
[test 3a078d4] update branch test
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 ddd
[1]+  Done                    echo ddd >> ddd && git add .
# git push # 不带参数执行git push可以看到本地更新的2个分支都推送了新的change到服务器端。详细解释参考 http://loveky2012.blogspot.com/2012/08/default-behaviour-of-git-pull-and-git-push.html
Counting objects: 4, done.
Delta compression using up to 24 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 295 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/gewang/test/test/parent.git
   985c04f..c3d70fd  master -> master
   c3d70fd..3a078d4  test -> test
# cd ../child2 # 切换到第二个工作repo,执行git pull在将server端change拿到本地后会报错,因为配置里没有关于test分支的mrege信息。(这是由于之前push test分支时没有加-u参数导致的)
# git pull
From /home/gewang/test/test/parent
   985c04f..c3d70fd  master     -> origin/master
   c3d70fd..3a078d4  test       -> origin/test
You asked me to pull without telling me which branch you
want to merge with, and 'branch.test.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details.

If you often merge with the same branch, you may want to
use something like the following in your configuration file:
    [branch "test"]
    remote = <nickname>
    merge = <remote-ref>

    [remote "<nickname>"]
    url = <url>
    fetch = <refspec>

See git-config(1) for details.

# git branch --set-upstream test origin/test # 手工配置关联
Branch test set up to track remote branch test from origin.
# git pull # 再次pull即可
Updating c3d70fd..3a078d4
Fast-forward
 ddd |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 ddd

#13 楼 @chairy11

除非你有明确的目标,否则不用手动去 merge,否则出问题的可能更大

git pull 对我来说最省事也最不容易出错的

关于是不是省事这点不评论,但就容不容易出错来说 pull 和 merge 没有谁比谁好这说法

#18 楼 @loveky 谢谢…… 话说,我刚开了个 feature,“git flow feature start gem_related” 又“git add .”了下,还没有 commits 过,现在觉得这个 feature 名字起得太恶心了,想改名,有这个功能吗?用什么命令行啊?

#20 楼 @chairy11

try git branch -m oldname newname

#22 楼 @loveky 再问个哦,我的 assets/images 文件夹下面,除了 icons 文件夹,其它的都 gitignore,难道不应该是在.gitignore 文件夹里写: /app/assets/images ! /app/assets/images/icons 吗?为什么我 git add .结果没有显示 icons 文件夹?

#24 楼 @chairy11

try

app/assets/images/*
! app/assets/images/icons

#25 楼 @loveky 我现在是 images 下面有 icons 文件夹,而且里面有图片的。但我用了上面两句(其中第二个!后面没用空格),git status 显示: Untracked files: app/assets/images/

没说是 icons,这个不对吧?

#27 楼 @loveky 奇怪,是我的 IDE 延时吗?之前问你的时候,我也已经 git add . 过的啊,但没有。 这次用 git add . ,貌似又好了。

Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   .gitignore
#   new file:   app/assets/images/icons/avatar.jpeg
#   new file:   app/assets/images/icons/logo_text.png
#   new file:   app/assets/images/icons/shortcut.ico

谢谢:)

学这么多还不如用 grb .... https://github.com/jinzhu/grb

匿名 #32 2013年11月23日

跟帖子沾个光,最近在 ubuntu 上配置 git 能连通,但是无法从 github 上 clone 和 pull 等很多操作,不知道为什么。 异常: Permission denied (publickey). fatal: Could not read from remote repository. 求大神们帮忙

#32 楼 @TREE 我小菜鸟,但感觉你是没加 Ssh 或者进行用户验证之类...

匿名 #35 2013年11月23日

@chairy11 这个是肯定加了,测试是连通了。目前情况是,我自己的两台电脑都用这一个 github 帐号,老电脑做任何操作都没有问题,新电脑配置后,就测试是连通的,现在什么操作都不行。

#31 楼 @zhangjinzhu 这个工具试图解决的问题是什么呢?

repo 的简介是A tool to simplify working with remote branches, 但是 rm 操作还会删除本地的分支,会否有歧义?

同时还发现个小问题,如果在 master 上进行 rm master 操作,最后的 branch -d 会有问题吧

38 楼 已删除
39 楼 已删除
40 楼 已删除

#40 楼 @TREE Hi treeran! You've successfully authenticated, but GitHub does not provide shell access.

没问题啊,试试 clone。。

匿名 #42 2013年11月23日

@loveky 感谢,以解决,今天重新打开电脑就可以了

@loveky

解决的问题不是这里写了么:

* rename `branch1` to `branch2`
  $ grb mv   [branch1] [branch2] [--explain]
* rename current branch to `branch`
  $ grb mv branch [--explain]
* add a remote repo
  $ grb remote_add `name` `repo path` [--explain]
* remove a remote repo
  $ grb remote_rm `name` [--explain]
* delete branch `branch`,default current_branch
  $ grb rm [branch] [--explain]
* pull branch `branch`,default current_branch
  $ grb pull [branch] [--explain]
* push branch `branch`, default current_branch
  $ grb push [branch] [--explain]
* create new branch `branch`
  $ grb new [branch] [--explain]
* prune dead remote branches
  $ grb prune

// repo 的简介是 A tool to simplify working with remote branches, 但是 rm 操作还会删除本地的分支,会否有歧义?

第一次用最好用 --explain 看看会做什么,熟悉以后就很方便了

// 同时还发现个小问题,如果在 master 上进行 rm master 操作,最后的 branch -d 会有问题吧

明知删除当前所在分支有问题,就用grb remote_rm master 么,或者换个本地分支 ;)

#43 楼 @zhangjinzhu

第一次用最好用 --explain 看看会做什么,熟悉以后就很方便了

README 可以写的更详细些,否则不知道如何操作远程分支的用户看了--explain 估计也不知道是什么意思

明知删除当前所在分支有问题,就用 grb remote_rm master 么,或者换个本地分支 ;)

可以在代码里加个判断的 :)

#4 楼 @nightire 能加个 Q 么?有些前端的小问题想请教一下你呢……

分享一下在网上看到的这张图,非常清晰明了的解答这个问题:

timlen 回复

请问图还能记得在哪里看的吗 感觉超级清楚的解释了呢! 有没有一系列的图呀

感谢⁽⁽ଘ( ˊᵕˋ )ଓ⁾⁾

需要 登录 后方可回复, 如果你还没有账号请 注册新账号