Git 少用 Pull 多用 Fetch 和 Merge(转)
英文原文:git: fetch and merge, don’t pull
This is too long and rambling, but to steal a joke from Mark Twain Blaise Pascal I haven’t had time to make it shorter yet. There is some discussion of this post on the git mailing list, but much of it is tangential to the points I’m trying to make here. One of the git tips that I find myself frequently passing on to people is:
The problem with git pull is that it has all kinds of helpful magic that means you don’t really have to learn about the different types of branch in git. Mostly things Just Work, but when they don’t it’s often difficult to work out why. What seem like obvious bits of syntax for git pull may have rather surprising results, as even a cursory look through the manual page should convince you. The other problem is that by both fetching and merging in one command, your working directory is updated without giving you a chance to examine the changes you’ve just brought into your repository. Of course, unless you turn off all the safety checks, the effects of a git pull on your working directory are never going to be catastrophic, but you might prefer to do things more slowly so you don’t have to backtrack. |
译者信息![]() 本文有点长而且有点乱,但就像Mark Twain Blaise Pascal的笑话里说的那样:我没有时间让它更短些。在Git的邮件列表里有很多关于本文的讨论,我会尽量把其中相关的观点列在下面。 我最常说的关于git使用的一个经验就是:
git pull的问题是它把过程的细节都隐藏了起来,以至于你不用去了解git中各种类型分支的区别和使用方法。当然,多数时候这是没问题的,但一旦代码有问题,你很难找到出错的地方。看起来git pull的用法会使你吃惊,简单看一下git的使用文档应该就能说服你。 将下载(fetch)和合并(merge)放到一个命令里的另外一个弊端是,你的本地工作目录在未经确认的情况下就会被远程分支更新。当然,除非你关闭所有的安全选项,否则git pull在你本地工作目录还不至于造成不可挽回的损失,但很多时候我们宁愿做的慢一些,也不愿意返工重来。 |
BranchesBefore I explain the advice about git pull any further it’s worth clarifying what a branch is. Branches are often described as being a “line of development”, but I think that’s an unfortunate expression since:
I would suggest that you think of branches in terms of what defines them: they’re a name for a particular commit and all the commits that are ancestors of it, so each branch is completely defined by the SHA1sum of the commit at the tip. This means that manipulating them is a very lightweight operation – you just change that value. |
译者信息![]() 分支(Branches) 在说git pull之前,我们需要先澄清分支的概念(branches)。很多人像写代码似的用一行话来描述分支是什么,例如:
我认为你应该这样来理解分支的概念:它是用来标记特定的代码提交,每一个分支通过SHA1sum值来标识,所以对分支进行的操作是轻量级的--你改变的仅仅是SHA1sum值。 |
This definition has some perhaps unexpected implications. For example, suppose you have two branches, “stable” and “new-idea”, whose tips are at revisions E and F: A-----C----E ("stable") So the commits A, C and E are on “stable” and A, B, D and F are on “new-idea”. If you then merge “new-idea” onto “stable” with the following commands: git checkout stable # Change to work on the branch "stable" … then you have the following: A-----C----E----G ("stable") If you carry on committing on “new idea” and on “stable”, you get: A-----C----E----G---H ("stable") So now A, B, C, D, E, F, G and H are on “stable”, while A, B, D, F and I are on “new-idea”. Branches do have some special properties, of course – the most important of these is that if you’re working on a branch and create a new commit, the branch tip will be advanced to that new commit. Hopefully this is what you’d expect. When merging with git merge, you only specify the branch you want to merge into the current one, and only your current branch advances. |
译者信息![]() 这个定义或许会有意想不到的影响。比如,假设你有两个分支,“stable” 和 “new-idea”, 它们的顶端在版本 E 和 F: A-----C----E ("stable") 所以提交(commits) A, C和 E 属于“stable”,而 A, B, D 和 F 属于 “new-idea”。如果之后你用下面的命令 将“new-idea” merge 到 “stable” : git checkout stable # Change to work on the branch "stable" …那么你会得到这个: A-----C----E----G ("stable") 要是你继续在“new idea” 和“stable”分支提交, 会得到: A-----C----E----G---H ("stable") 因此现在A, B, C, D, E, F, G 和 H 属于 “stable”,而A, B, D, F 和 I 属于 “new-idea”。 当然了,分支确实有些特殊的属性——其中最重要的是,如果你在一个分支进行作业并创建了一个新的提交(commits),该分支的顶端将前进到那个提交(commits)。这正是你所希望的。当用git merge 进行合并(merge)的时候,你只是指定了要合并到当前分支的那个并入分支,以及当前分支的当前进展。 |
Another common situation where this view of branches helps a lot is the following: suppose you’re working on the main branch of a project (called “master”, say) and realise later that what you’ve been doing might have been a bad idea, and you would rather it were on a topic branch. If the commit graph looks like this: last version from another repository Then you separate out your work with the following set of commands (where the diagrams show how the state has changed after them): git branch dubious-experiment M---N-----O----P---Q ("master" and "dubious-experiment") git checkout master # Be careful with this next command: make sure "git status" is This is something I seem to end up doing a lot… :) |
译者信息![]() 另一个表明使用分支会有很大帮助的观点的常见情形是:假设你直接工作在一个项目的主要分支(称为“主版本”),当你意识到你所做的可能是一个坏主意时已经晚了,这时你肯定宁愿自己是工作在一个主题分支上。如果提交图看起来像这样: last version from another repository 那么你把你的工作用下面的一组命令分开做(如图显示的是执行它们之后所更改的状态): git branch dubious-experiment M---N-----O----P---Q ("master" and "dubious-experiment") git checkout master # Be careful with this next command: make sure "git status" is 这是个看起来我最终做了很多的事情。 |
Types of BranchesThe terminology for branches gets pretty confusing, unfortunately, since it has changed over the course of git’s development. I’m going to try to convince you that there are really only two types of branches. These are: (a) “Local branches”: what you see when you type git branch, e.g. to use an abbreviated example I have here: $ git branch (b) “Remote-tracking branches”: what you see when you type git branch -r, e.g.: $ git branch -r The names of tracking branches are made up of the name of a “remote” (e.g. origin, cognac, fruitfly) followed by “/” and then the name of a branch in that remote respository. (“remotes” are just nicknames for other repositories, synonymous with a URL or the path of a local directory – you can set up extra remotes yourself with “git remote”, but “git clone” by default sets up “origin” for you.) |
译者信息![]() 分支类型 分支这个术语不太容易理解,而且在git的开发过程中发生了很多变化。但简单来说git的分支只有两种: a)“本地分支(local branches)” ,当你输入“git branch”时显示的。例如下面这个小例子: $ git branch b)“远程跟踪分支(Remote-tracking branches)” ,当你输入“git branch -r”是显示的,如: $ git branch -r 从上面的输出可以看到,跟踪分支的名称前有一个“远程的”标记名称(如 :origin, cognac, fruitfly)后面跟一个“/”,然后远程仓库里分支的真正名称。(“远程名称”是一个代码仓库别名,和本地目录或URL是一个含义,你可以通过"git remote"命令自由定义额外的“远程名称”。但“git clone”命令默认使用的是“origin”这个名称。) |
If you’re interested in how these branches are stored locally, look at the files in:
Both types of branches are very similar in some respects – they’re all just stored locally as single SHA1 sums representing a commit. (I emphasize “locally” since some people see “origin/master” and assume that in some sense this branch is incomplete without access to the remote server – that isn’t the case.) Despite this similarity there is one particularly important difference:
So what you mostly do with remote-tracking branches is one of the following:
|
译者信息![]() 如果你对分支在本地是如何存储感兴趣的话,看看下面文件:
两种类型的分支在某些方面十分相似-它们都只是在本地存储一个表示提交的SHA1校验和。(我强调“本地”,因为许多人看到"origin/master" 就认为这个分支在某种意义上说是不完整的,没有访问远端服务器的权限- 其实不是这种情况。)
因此,你对远端跟踪分支最多能做的是下面事情中的一件:
|
Creating local branches based on remote-tracking branchesIf you want to create a local branch based on a remote-tracking branch (i.e. in order to actually work on it) you can do that with git branch –track or git checkout –track -b, which is similar but it also switches your working tree to the newly created local branch. For example, if you see in git branch -r that there’s a remote-tracking branch called origin/refactored that you want, you would use the command: git checkout --track -b refactored origin/refactored In this example “refactored” is the name of the new branch and “origin/refactored” is the name of existing remote-tracking branch to base it on. (In recent versions of git the “–track” option is actually unnecessary since it’s implied when the final parameter is a remote-tracking branch, as in this example.) |
译者信息![]() 基于远程跟踪分支创建本地分支如果你想基于远程跟踪分支创建本地分支(在本地分支上工作),你可以使用如下命令:git branch –track或git checkout –track -b,两个命令都可以让你切换到新创建的本地分支。例如你用git branch -r命令看到一个远程跟踪分支的名称为“origin/refactored”是你所需要的,你可以使用下面的命令: git checkout --track -b refactored origin/refactored 在上面的命令里,“refactored”是这个新分支的名称,“origin/refactored”则是现存远程跟踪分支的名称。(在git最新的版本里,例子中‘-track’选项已经不需要了,如果最后一个参数是远程跟踪分支,这个参数会被默认加上。) |
The “–track” option sets up some configuration variables that associate the local branch with the remote-tracking branch. These are useful chiefly for two things:
Your branch and the tracked remote branch 'origin/master' … or: Your branch is behind the tracked remote branch The configuration variables that allow this are called “branch.<local-branch-name>.merge” and “branch.<local-branch-name>.remote”, but you probably don’t need to worry about them. |
译者信息![]() “–track”选项会设置一些变量,来保持本地分支和远程跟踪分支的相关性。他们对下面的情况很有用:
Your branch and the tracked remote branch 'origin/master' 或者: Your branch is behind the tracked remote branch 允许使用的配置变量是:“branch.<local-branch-name>.merge”和“branch.<local-branch-name>.remote”,但通常情况下你不用考虑他们的设置。 |
You have probably noticed that after cloning from an established remote repository git branch -r lists many remote-tracking branches, but you only have one local branch. In that case, a variation of the command above is what you need to set up local branches that track those remote-tracking branches.
Now, let’s look at an example of how to update from a remote repository, and then how to push changes to a new repository. |
译者信息![]() 当从远程代码仓库创建一个本地分支之后,你会注意到,“git branch -r”能列出很多远程跟踪分支,但你的电脑上只有一个本地分支,你需要给上面的命令设置一个参数,来指定本地分支和远程分支的对应。
下面我们来看一个例子,如何从远程分支中更新本地代码,以及如何把本地分支推送到一个新的远程仓库中。 |
Updating from a Remote RepositorySo, if I want get changes from the remote repository called “origin” into my local repository I’ll type git fetch origin and you might see some output like this: remote: Counting objects: 382, done. The most important bits here are the lines like these: 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030 The first line of these two shows that your remote-tracking branch origin/debian-release-20081030 has been advanced from the commit 3036acc to 9eb5e40. The bit before the arrow is the name of the branch in the remote repository. The second line similarly show that since we last did this, a new remote tracking branch has been created. (git fetch may also fetch new tags if they have appeared in the remote repository.) |
译者信息![]() 从远端仓库进行更新如果我想从远端的源仓库更新到本地的代码仓库,可以输入“git fetch origin”的命令,该命令的输入类似如下格式: remote: Counting objects: 382, done. 最重要的是这两行: 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030 第一行表明远端的origin/debian-release-20081030分支的提交(commit)ID已经从3036acc更新为9eb5e40。箭头前的部分是远端分支的名称。第二行是我们采取的动作,创建远程跟踪分支(如果远程仓库有新的tags,git fetch也会一并下载到本地)。 |
Git 少用 Pull 多用 Fetch 和 Merge(转)的更多相关文章
- Git 少用 Pull 多用 Fetch 和 Merge
本文有点长而且有点乱,但就像Mark Twain Blaise Pascal的笑话里说的那样:我没有时间让它更短些.在Git的邮件列表里有很多关于本文的讨论,我会尽量把其中相关的观点列在下面. 我最常 ...
- 【转】Git 少用 Pull 多用 Fetch 和 Merge
原文网址:http://www.cnblogs.com/flying_bat/p/3408634.html 本文有点长而且有点乱,但就像Mark Twain Blaise Pascal的笑话里说的那样 ...
- Git 少用 Pull 多用 Fetch 和 Merge 【已翻译100%】【转】
本文转载自:https://www.oschina.net/translate/git-fetch-and-merge?lang=chs&page=1# 本文有点长而且有点乱,但就像Mark ...
- Git中pull对比fetch和merge
本文参考于:http://www.zhanglian2010.cn/2014/07/git-pull-vs-fetch-and-merge/ 使用git fetch和git pull都可以更新远程仓库 ...
- git 的 pull、fetch、merge
1.pull = fetch + merge In the simplest terms, git pull does a git fetch followed by a git merge. You ...
- git 拉取和获取 pull 和 fetch 区别
使用Git 直接提交的话 直接 push 获取最新版本 有两种 拉取 和 获取 pull 和 fetch git pull 从远程拉取最新版本 到本地 自动合并 merge ...
- git pull fatal: refusing to merge unrelated histories
1.首先我github有个远程仓库,然后我本地有个仓库 本地仓库我新添加了一个文件,然后我去关联(git remote add origin git@github.com:qshilary/gitte ...
- git 拉取和获取 pull 和 fetch 区别【转】
本文转载自:http://blog.csdn.net/u010094934/article/details/52775653 使用git 直接提交的话 直接 push 获取最新版本 有两种 ...
- TortoiseGit - pull 与 fetch
Git的Pull其实是fetch与Merge两个命令的合并. 平时遇到的问题是,在本地分支进行了一些修改,准备提交.但是怕提交前有其他人push了新的代码.于是想在提交前,看看远程仓库上的log.这时 ...
随机推荐
- SQL Server,Access数据库查询易混点和C#中parameter指定参数长度的优缺点
在学校的时候就经常做一些网站,所以这次在公司实习,组长第一次给了一个企业的网站还是很快的完成了.中间并没有遇到什么大的问题,但是还是遇到了两个新手非常容易混淆的小问题,所以拿出来跟大家分享一下. 主要 ...
- 怎样在Android开发中FPS游戏实现的两种方式比较
怎样在Android开发中FPS游戏实现的两种方式比较 如何用Android平台开发FPS游戏,其实现过程有哪些方法,这些方法又有哪些不同的地方呢?首先让我们先了解下什么是FPS 英文名:FPS (F ...
- mac_Mac环境下怎样编写HTML代码?
在Mac环境下,使用默认的文本编辑器编写的HTML的源代码, 使用不同的浏览器打开后,依旧还是显示源代码 推荐使用UltraEdit,问题就迎刃而解了
- how to fix the cwm/miui recovery status 2 error
Frequent issues: --------------------- If you report an issue without a log and/or without details, ...
- CentOS 6.3 安装 samba 共享(转)
PHP环境在linux下,但是开发的时候用的是windows,于是我用了samba将linux的一个目录共享,然后在windows上做映射,这样就可以直接在windows下编辑linux上的文件了 首 ...
- 《炉石传说》建筑设计欣赏(6):卡&在执行数据时,组织能力
上一篇文章我们看到了<炉石传说>核心存储卡的数据,今天,我们不断探索卡&身手. 基本的类 通过之前的分析,卡牌&技能涉及到几个类体系:Entity.Actor.Card.S ...
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- chrome 关闭自己主动更新
一不小心,把chrome更新成了37, chrome 37不支持模态窗体[ window.showModalDialog() ],折腾死人了. 实在抵不住,仅仅好降级成36.0.1985.143m 至 ...
- [LeetCode202]Happy Number判断一个数是不是happy number
题目: Write an algorithm to determine if a number is "happy". A happy number is a number def ...
- oracle在imp订单具体解释
oracle在imp订单具体解释 Oracle导入实用程序(Import utility)同意从数据库中提取数据,和写入数据到一个操作系统文件项目.imp所用的基本格式:imp[username[/p ...