GIT使用经验

不要用git pull,用git fetch和git merge代替它。

git pull的问题是它把过程的细节都隐藏了起来,以至于你不用去了解git中各种类型分支的区别和使用方法。当然,多数时候这是没问题的,但一旦代码有问题,你很难找到出错的地方。看起来git pull的用法会使你吃惊,简单看一下git的使用文档应该就能说服你。

将下载(fetch)和合并(merge)放到一个命令里的另外一个弊端是,你的本地工作目录在未经确认的情况下就会被远程分支更新。当然,除非你关闭所有的安全选项,否则git pull在你本地工作目录还不至于造成不可挽回的损失,但很多时候我们宁愿做的慢一些,也不愿意返工重来。

分支(Branches)

在说git pull之前,我们需要先澄清分支的概念(branches)。很多人像写代码似的用一行话来描述分支是什么,例如:

  • 准确而言,分支的概念不是一条线,而类似于开发中的有向无环图
  • 分支类似于一个重量级的大对象集合。
  • 我认为你应该这样来理解分支的概念:它是用来标记特定的代码提交,每一个分支通过SHA1sum值来标识,所以对分支进行的操作是轻量级的--你改变的仅仅是SHA1sum值。

    这个定义或许会有意想不到的影响。比如,假设你有两个分支,“stable” 和 “new-idea”, 它们的顶端在版本 E 和 F:

      A-----C----E ("stable")
           B-----D-----F ("new-idea")

    所以提交(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"
        git merge new-idea    # Merge in "new-idea"

    …那么你会得到这个:

      A-----C----E----G ("stable")
       \             /
        B-----D-----F ("new-idea")

    要是你继续在“new idea” 和“stable”分支提交, 会得到:

      A-----C----E----G---H ("stable")
       \             /
        B-----D-----F----I ("new-idea")

    因此现在A, B, C, D, E, F, G 和 H 属于 “stable”,而A, B, D, F 和 I 属于 “new-idea”。

    当然了,分支确实有些特殊的属性——其中最重要的是,如果你在一个分支进行作业并创建了一个新的提交(commits),该分支的顶端将前进到那个提交(commits)。这正是你所希望的。当用git merge 进行合并(merge)的时候,你只是指定了要合并到当前分支的那个并入分支,以及当前分支的当前进展。

    另一个表明使用分支会有很大帮助的观点的常见情形是:假设你直接工作在一个项目的主要分支(称为“主版本”),当你意识到你所做的可能是一个坏主意时已经晚了,这时你肯定宁愿自己是工作在一个主题分支上。如果提交图看起来像这样:

       last version from another repository
          |
          v
      M---N-----O----P---Q ("master")

    那么你把你的工作用下面的一组命令分开做(如图显示的是执行它们之后所更改的状态):

      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
      # clean, you‘re definitely on "master" and the
      # "dubious-experiment" branch has the commits you were working
      # on first...
    
      git reset --hard <SHA1sum of commit N>
    
           ("master")
      M---N-------------O----P---Q ("dubious-experiment")
    
      git pull # Or something that updates "master" from
               # somewhere else...
    
      M--N----R---S ("master")
                 O---P---Q ("dubious-experiment")

    这是个看起来我最终做了很多的事情。

    分支这个术语不太容易理解,而且在git的开发过程中发生了很多变化。但简单来说git的分支只有两种:

    a)“本地分支(local branches)” ,当你输入“git branch”时显示的。例如下面这个小例子:

           $ git branch
             debian
             server
           * master

    b)“远程跟踪分支(Remote-tracking branches)” ,当你输入“git branch -r”是显示的,如:

           $ git branch -r
           cognac/master
           fruitfly/server
           origin/albert
           origin/ant
           origin/contrib
           origin/cross-compile

    从上面的输出可以看到,跟踪分支的名称前有一个“远程的”标记名称(如 :origin, cognac, fruitfly)后面跟一个“/”,然后远程仓库里分支的真正名称。(“远程名称”是一个代码仓库别名,和本地目录或URL是一个含义,你可以通过"git remote"命令自由定义额外的“远程名称”。但“git clone”命令默认使用的是“origin”这个名称。)

    如果你对分支在本地是如何存储感兴趣的话,看看下面文件:

  •   .git/refs/head/[本地分支]
  •   .git/refs/remotes/[正在跟踪的分支]
  • 两种类型的分支在某些方面十分相似-它们都只是在本地存储一个表示提交的SHA1校验和。(我强调“本地”,因为许多人看到"origin/master" 就认为这个分支在某种意义上说是不完整的,没有访问远端服务器的权限- 其实不是这种情况。)

    不管如何相似,它们还是有一个特别重大的区别:

  •   更改远端跟踪分支的安全方法是使用git fetch或者是作为git-push副产品,你不能直接对远端跟踪分支这么操作。相反,你总得切换到本地分支,然后创建可移动到分支顶端的新提交 。
  • 因此,你对远端跟踪分支最多能做的是下面事情中的一件:

  • 使用git fetch 更新远端跟踪分支
  • 合并远端跟踪分支到当前分支
  • 根据远端跟踪分支创建本地分支
  • 基于远程跟踪分支创建本地分支

    如果你想基于远程跟踪分支创建本地分支(在本地分支上工作),你可以使用如下命令:git branch –trackgit checkout –track -b,两个命令都可以让你切换到新创建的本地分支。例如你用git branch -r命令看到一个远程跟踪分支的名称为“origin/refactored”是你所需要的,你可以使用下面的命令:

        git checkout --track -b refactored origin/refactored

    在上面的命令里,“refactored”是这个新分支的名称,“origin/refactored”则是现存远程跟踪分支的名称。(在git最新的版本里,例子中‘-track’选项已经不需要了,如果最后一个参数是远程跟踪分支,这个参数会被默认加上。)

    “–track”选项会设置一些变量,来保持本地分支和远程跟踪分支的相关性。他们对下面的情况很有用:

  • git pull命令下载新的远程跟踪分支之后,可以知道合并到哪个本地分支里
  • 使用git checkout检查本地分支时,可以输出一些有用的信息:
  •     Your branch and the tracked remote branch ‘origin/master‘
        have diverged, and respectively have 3 and 384 different
        commit(s) each.

    或者:

        Your branch is behind the tracked remote branch
        ‘origin/master‘ by 3 commits, and can be fast-forwarded.

    允许使用的配置变量是:“branch.<local-branch-name>.merge”和“branch.<local-branch-name>.remote”,但通常情况下你不用考虑他们的设置。

    当从远程代码仓库创建一个本地分支之后,你会注意到,“git branch -r”能列出很多远程跟踪分支,但你的电脑上只有一个本地分支,你需要给上面的命令设置一个参数,来指定本地分支和远程分支的对应。

    有一些术语上的说法容易混淆需要注意一下:“track”在当作参数"-track"使用时,意思指通过本地分支对应一个远程跟踪分支。在远程跟踪分支中则指远程代码仓库中的跟踪分支。有点绕口。。。

    下面我们来看一个例子,如何从远程分支中更新本地代码,以及如何把本地分支推送到一个新的远程仓库中。

    从远端仓库进行更新

    如果我想从远端的源仓库更新到本地的代码仓库,可以输入“git fetch origin”的命令,该命令的输入类似如下格式:

      remote: Counting objects: 382, done.
      remote: Compressing objects: 100% (203/203), done.
      remote: Total 278 (delta 177), reused 103 (delta 59)
      Receiving objects: 100% (278/278), 4.89 MiB | 539 KiB/s, done.
      Resolving deltas: 100% (177/177), completed with 40 local objects.
      From ssh://[email protected]/srv/git/fiji
         3036acc..9eb5e40  debian-release-20081030 -> origin/debian-release-20081030
       * [new branch]      debian-release-20081112 -> origin/debian-release-20081112
       * [new branch]      debian-release-20081112.1 -> origin/debian-release-20081112.1
         3d619e7..6260626  master     -> origin/master

    最重要的是这两行:

         3036acc..9eb5e40  debian-release-20081030 -> origin/debian-release-20081030
       * [new branch]      debian-release-20081112 -> origin/debian-release-20081112

    第一行表明远端的origin/debian-release-20081030分支的提交(commit)ID已经从3036acc更新为9eb5e40。箭头前的部分是远端分支的名称。第二行是我们采取的动作,创建远程跟踪分支(如果远程仓库有新的tags,git fetch也会一并下载到本地)。

    时间: 2024-12-05 22:35:35

    GIT使用经验的相关文章

    git 使用经验

    1, 切换分支: git  checkout  <分支名字>: git checkout clhandle 2,查看有哪些分支: git  branch ; 查看远端有哪些分支: git branch -r 3,拉取远端分支:(本地没有该分支的时候???) git fetch origin cl_handle: clhandle; 注意: fetch  将远端拉到本地 但是 不合并: origin 表示远端, cl_handle 是远端的分支名 clhandle 如果本地没有这个分支 就会创建

    Git使用经验总结

    1. Git如何获得两个版本间所有变更的文件列表 用"git log"或者"git log|grep <name>"查到关注的版本的哈希值,然后 git diff dd1b3f4d24e9bc8813e0ddb68396684aa2cd684d 83ca581804524f0d271c82779b102bb20cca32ce --stat 或者 git diff dd1b3 83ca5 --stat 前4-6位就可区分 2. 典型的git checkou

    git使用经验(一)

    在使用Git Push代码到数据仓库时,提示如下错误: [remote rejected] master -> master (branch is currently checked out) 错误原型 remote: error: refusing to update checked out branch: refs/heads/master remote: error: By default, updating the current branch in a non-bare reposit

    Git详解之三 Git分支

    相关文档 — 更多 Git 基础培训.ppt GIT 使用经验.ppt GIT 介绍.pptx GIT 分支管理是一门艺术.docx Eclipse上GIT插件EGIT使用手册.docx git/github学习笔记.doc git 版本控制系统.docx Git开发管理之道.pdf Git内部培训资料.pptx Git权威指南-第5篇-第32章-Gerrit.pdf Gitolite 构建 Git 服务器.pdf 版本控制之道 - 使用Git.pdf Git使用指南(中文).pdf Git-C

    贯穿Git使用

    >本文总结于自己在工作中对Git使用经验的总结,重点是使用.对于Git相关理论网上很多,可与SVN作对比由此深入,这里简单指出最重要的几点,有兴趣可深入. <p>git checkout -b Lxf_Local_IPPM origin/16B_Featcher_IPPM<p>git pull -r origin 16B_Featcher_IPPM<p>git clean -fdx<p>git checkout 16B_Featcher_IPPM<

    git 使用那些事儿

    git使用经验总结 一.克隆项目 1.通过GitLab查询 项目  的地址 2.克隆项目(gitAddr需从gitLab中查得) git clone gitAddr 3.切分支 切到dev分支 git checkout dev 4.转换为eclipse项目 mvn eclipse:eclipse 5.导入到eclipse中 二.提交流程 1. 拉代码(dev是分支名称.本命令,在分支目录下执行) git pull origin dev begin if [正常] 2. 提交所有变化 到 暂存区

    Git内部原理探索

    目录 前言 Git分区 .git版本库里的文件/目录是干什么的 Git是如何存储文件信息的 当我们执行git add.git commit时,Git背后做了什么 Git分支的本质是什么 HEAD引用 参考 @ 前言 洞悉技术的本质,可以让我们在层出不穷的框架面前仍能泰然处之.用了那么久的 Git,不懂点内部原理,那可不行!懂点原理可以让我们遇到问题的时候能够更好更快的理清解决问题的思路.博客原文 要真正读懂本文可能需要以下基础: 有 Git 使用经验 对 Git 的三个分区有所了解 熟悉常用的

    指导思想

    告诉我,我可能转眼就忘:较我,我会牢记在心:参与其中,我会心领神会.--本杰明·富兰克林 不论读多少书,学习知识的最佳方式是将其应用于实践. 比如:阅读了<git使用经验(已读70%)>,仅需要阅读其中的一部分知识,其他的部分需要结合实践:因为是工作的需要,不能将大部分时间都用在学习上,而忽略了业务水平的提升. 教训:把工作做得尽善尽美,就得学会找到所有可能失败的原因:如果规避了大部分可能失败的行为和局面,那么你成功的概率将大大增加.比如在工作中,学会去在"事前"验证可能的

    Eclipse的Git工具EGit的使用经验

    由于项目需要,简单看了一下这个工具的使用.发现在最新版的Eclipse Luna中似乎已经集成这个工具了,对于旧一点版本的Eclipse,可以在:http://www.eclipse.org/egit/ 查看安装方法. 安装好并重启Eclipse之后,我们可以切换到Git视图,在这里可以将我们已经在公开或私有GIt网站上的Repository Clone到本地.基本步骤都很简单,到了"Local Destination"这一步的时候,有些设置需要注意,假设我们只使用如下图所示的默认设置