Git中级教程

本文章最初发布在 XJHui's Blog,未经允许,任何人禁止转载!

<font color="red" style="font-weight:700">注意:</font>最新修改版本已发布在 这里,点击前往查看!

关于笔记

  1. 视频地址:Git(中级)教程(12h深入掌握git)(28p)
  2. 学前基础:
    • linux
    • github
  3. 学后技能:
    • git底层、高层命令
    • git分支、存储、后悔药、标签
    • git团队协作、Pull Request

版本控制

集中式(svn)

  1. 原理:服务器存放项目的所有版本,工作时从服务器下载项目最新版本,工作完成后将代码提交到服务器

  2. 原理图:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/10/27/b206f8c4bdb2d6f5dbd2b623fe120e69.png" width="70%"/>

分布式(git)

  1. 原理:每台电脑中都存放了项目的所有版本,即使服务器故障也不会影响工作更不会将丢失项目

  2. 原理图:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/10/27/ec58da5fa6ff1b06991d7cb1a8a6b2e2.png" width="70%"/>

差异比较

  1. 存储方式:svn存储版本差异,git存储所有版本

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/60e5fac332de40bd7555eef38f9efdeb.png" width="70%"/>

    注意:git是先压缩后存储,尽管存储占用比svn大,但不会大太多

  2. 安全性:

    • svn:工作时只会下载项目最新版本,如果服务器存储故障,就无法从员工电脑恢复项目所有版本
    • git:每位员工电脑上都有项目的所有版本,即使服务器存储故障,任意一位员工都能恢复整个项目
  3. 版本回退速度:

    • svn:存储的是版本差异,每回退一个版本都需要打一次补丁,导致回退速度慢
    • git:存储所有版本,只要找到该版本对应的提交对象,就可直接回退到该版本
  4. 服务器故障时:

    • svn:新写的代码不满意,不能回退到初始版本
    • git:本地操作不受服务器限制,可任意提交、回退
  5. 总结:

    • svn:存储占用小
    • git:安全、高效

git

简史

  1. 创始人:Linus Benedict Torvalds(林纳斯·托瓦兹)

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/6d276f08504285bb2bb5cd2296de4179.png" width="70%"/>

  2. git起源:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/10/28/febded7eba7d7f763042f3143a6e92b6.png" width="70%"/>

安装

  1. 下载访问: https://xjhui.lanzoux.com/iap7Odtezyf,感谢:蓝奏云

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/10/28/1de7c1722930944648b04fed1d67d29e.png" width="70%"/>

    注意:如果与您的电脑版本不匹配,请访问:https://git-scm.com/download/win 下载指定版本

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/10/28/567e1ec43892b8c7a24665f01c8b16a1.png" width="70%"/>

  2. 安装:一路next

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/61641f7278d1036c94e023f806b8eee3.png" width="50%"/>

  3. 验证安装:桌面右键,出现框选内容代表安装成功

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/10/28/dcedc988921b8a572b344e2a5d946f08.png" width="70%"/>

初始化

  1. 命令:

    git init  # 初始化一个git仓库
    
  2. 案例:在/workspace下初始化一个git仓库

    • 文件夹内右键选择 Git Bash Here

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/02/b598c9b0cbd0bdd9880f5f4920d43298.png" width="70%"/>

    • 输入指令: git init

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/02/17dca36e4c1fb453e27dbf9ca1ca8fb2.png" width="70%"/>

      注意:.git为隐藏文件,若不显示请点击 查看 -> 勾选 隐藏的项目

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/07575091edd6adf64848a7cf01f462d5.png" width="70%"/>

  3. git文件(.git文件夹内):

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/02/449bac2bd15fb3b6b10ca0d33dc815e6.png" width="70%"/>

    文件功能:

    • hooks:存放钩子文件(提交代码前、后要做的事,例如检查代码规范)
    • info:说明哪些文件不需要管理
    • objects:对象库(类似对象库,存放git对象、树对象、提交对象)
    • refs、HEAD:分支相关内容
    • description:仓库描述信息

git区域

  1. 三个区域:

    • 工作区:就是你在电脑里能看到的目录
    • 暂存区:一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们有时也把暂存区叫作索引(index)
    • 版本库:工作区有一个隐藏目录.git

    注意:暂存区是存在于版本库中的,而版本库是存在于工作区的

  2. 关系图:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/085586a0f984f0f70d5cf16e4f0ea97e.png" width="70%"/>

git底层概念

底层概念代码不需要掌握,但一定得懂

git对象

  1. 定义:通过 git hash-object -w 命令在objects目录下生成的对象都是git对象

  2. 生成git对象的方法:

    • 方法一:将字符串直接写入对象库

      • 语法:

        echo 'test content' | git hash-object -w --stdin
        

        参数功能:

        • -w:返回hash值并写入对象库,若不添加该参数则只返回hash值
        • --stdin:标准输入流读取字符串,不可省略

        运行结果:

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/34afcb75d2f8dfb6edd9038a5c110f9c.png" width="70%"/>

      • 查看value(字符串)值:

        • cat 命令:

          <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/9500df6a1dd9de6a9a4039cb7e6e7f24.png" width="70%"/>

        • git cat-file -p 命令:

          <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/cfb0deb5135afdb665e87c8177ad7baa.png" width="70%"/>

        • git cat-file -t 命令可查看git对象的类型:

          <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/ca6344aab567994bab6b249892ad5feb.png" width="70%"/>

    • 方法二:将文本文件中的字符串写入对象库

      • 语法:

        git hash-object -w 文件名
        

        参数功能:

        • -w:返回hash值并写入对象库,若不添加该参数则只返回hash值
        • 文件名:包含文本内容的文件,不可省略
      • 案例1:使用 git hash-object 命令将test.txt文件(v1版本)内容写入到对象库

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/646934e501849867c8d9b2520ae93f00.png" width="70%"/>

        命令:

        git hash-object -w test.txt
        

        运行结果:

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/48599e1ebecd03007278fa42abf3e289.png" width="70%"/>

      • 案例2:修改test.txt文件(v2版本),并再次写入对象库

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/e9a5f9f8b7a2079bb905bc7973daceb9.png" width="70%"/>

        命令:

        git hash-object -w test.txt
        

        运行结果:

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/0f7499991ea7c0b287d2d8091a7e5afa.png" width="70%"/>

        使用 find .git/objects/ -type f 命令查看所有git对象:

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/e1e8be1b37bdb00456433fbaf9763e7b.png" width="70%"/>

  3. git对象总结:git对象仅能存储文件的内容,对文件名称的存储却无能为力

树对象

  1. 定义:解决git对象无法存储文件名称的问题,创建树对象需要先将git对象放入暂存区

  2. 将git对象放入暂存区:

    • 放入前查看缓存区内容:

      git ls-files -s
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20s/b53fb9df77a4314d4959c4106be4394f.png" width="70%"/>

    • 将git对象放入暂存区:

      git update-index --add --cacheinfo 100644 a0423896973644771497bdc03eb99d5281615b51 test.txt
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/ad924c58a7b8e91cf5d4a2241f309eb5.png" width="70%"/>

      参数解释:

      • --add:文件首次加入暂存区时需要添加该参数
      • --cacheinfo:要添加的git对象位于git对象库中,而不是位于当前目录下
      • 文件类型:100644( 普通文件)、100755(可执行文件)、120000(符号链接)
    • 放入后再次查看缓存区内容:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/60fcd663b88168136eb2676dc15cc777.png" width="70%"/>

  3. 生成树对象:

    git write-tree
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20s/6ed644ddc30ac01b8638e8e8154c6001.png" width="70%"/>

    查看树对象类型:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/46ee0fba3cccb8fa5bafd468e9538033.png" width="70%"/>

    注意:树对象也会被存储到objects目录下:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/5fbbd6af63049e462c60a7b27a4ebd61.png" width="70%"/>

    git、树对象差异:git对象代表文件的一次次版本,树对象代表项目的一次次版本

  4. 树对象的不足:

    • objects文件中放置了git对象和树对象,很难区分开来
    • 有git、树对象但不知道提交人、提交时间、版本差异

提交对象

<img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20s/0c3f5b7ac1901b2155c48ee50da78d25.png" width="50%"/>

  1. 概念:

    • 创建树对象后就要创建一个提交对象,用来存储该树对象的具体信息(提交人、时间、注释等信息)
    • 每个提交对象分别指向一个树对象和一个父提交对象(第一个提交对象仅指向一个树对象)
  2. 创建提交对象:

    • 创建第一个提交对象:

      echo '注释' | git commit-tree 树对象
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/30ea6bdbbe14dd85211679c1a5ba1c41.png" width="70%"/>

      注意:第一个提交对象不需要指向父提交对象,但其他提交对象必须指向父提交对象

    • 创建其它提交对象:

    echo '注释' | git commit-tree 树对象 -p 父提交对象

    
    运行结果:
    
    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/03/9740faa72dff75a4235c671c4fdd9a9f.png" width="70%"/>
    
    查看提交对象内容:
    
    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20s/e350d2d85d6ec73cd3d6241f420567b8.png" width="70%"/>
    
    

命令总结

命令中所有对象(git、树、提交对象)都要用对应hash值代替

  1. git init:初始化git仓库
  2. 生成git对象:
    • echo "字符串" | git hash-object -w --stdin:将字符串写入对象库
    • git hash-object -w 文件名:将文件内容写入对象库
  3. 生成树对象:
    • git update-index --add --cacheinfo 文件类型 git对象:将git对象存入暂存区
    • git write-tree:生成树对象
  4. 生成提交对象:
    • echo "注释" | git commit-tree 树对象:生成第一个提交对象
    • echo "注释" | git commit-tree 树对象 -p 父提交对象:生成其它提交对象
  5. 查看对象信息:
    • git cat-file -t 对象:查看对象类型
    • git cat-file -p 对象:查看对象内容
    • git ls-file -s:查看暂存区内容
    • find .git/objects/ -type f:查看对象库中的所有对象

git高层命令

最基本流程

  1. git init:初始化git仓库

  2. git add ./:给所有文件生成git对象并添加到暂存区

    git hash-object -w 文件名  # 等同于该命令被执行n次(n=文件数目)
    git update-index --add --cacheinfo 文件类型 git对象
    

    注意:暂存区在版本库中,所以执行git add命令后git对象先进入版本库再进去暂存区

  3. git commit -m "提交备注":生成树对象和提交对象

    git write-tree  # 生成树对象
    echo "备注" | git commit-tree 树对象 -p 父提交对象  # 生成提交对象
    

查看文件

  1. 文件状态:未跟踪、已跟踪(已暂存、已提交、已修改)

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/37250eb2ea47e07f74bf6b14e269df17.png" width="70%"/>

  2. git status

    查看文件状态(未跟踪、已跟踪(已暂存,已提交,已修改))

    • 查看未跟踪文件的状态:

      echo "hello world!" > laofu.txt
      git status  # 查看文件状态
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/3ab95e072629a18a33b51414234a07a0.png" width="70%"/>

      注意:新建的文件为未跟踪状态

    • 查看已跟踪文件状态

      • 已暂存:

        git add laofu.txt  # 将文件放入暂存区,add后也可跟./或文件夹
        git status  # 查看文件状态
        

        运行结果:

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/052a17cb6b69af9a4982e74cba076b51.png" width="70%"/>

      • 已提交:

        git commit -m "提交注释"  # 将暂存区文件提交到版本库
        git status  # 查看文件状态
        

        运行结果:

        <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/87f02482cbb4f87671ce492b831e32ac.png" width="70%"/>

        注意:

        • 如果注释内容过多,可以使用git commit 命令在文件中键入注释:

          <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/1d2f7f56dd7fbf98749b8659ce183d0d.png" width="70%"/>

        • 对已跟踪文件,使用git commit命令时添加参数 -a,可跳过git add命令,直接提交到版本库

      • 已修改

        • 查看已提交的文件修改后状态:

          vim laofu.txt  # 修改已提交文件的内容
          git status  # 查看文件状态
          

          运行结果:

          <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/7edeaefc73b1ebe7535f4adad4183ec6.png" width="70%"/>

          注意:虽然改文件未被暂存,但已被跟踪,可以直接使用 git commit -m 命令提交到版本库

        • 查看已暂存的文件修改后的状态:

          git add ./  # 将文件添加到暂存区
          vim laofu.txt  # 修改已暂存文件的内容
          git status  # 查看文件状态
          

          运行结果:

          <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/bd197806a674bbb7e8a13743be61083e.png" width="70%"/>

          注意:已暂存的文件修改后会出现两种状态,必须再次执行git add命令,否则提交的内容还是上次暂存的版本

  3. git diff

    批量查看已跟踪文件的状态

    • 查看已跟踪的文件中哪些修改需要暂存:

      vim laofu.txt  # 修改文件,将其变为未暂存状态
      git diff  # 查看哪些更新需要暂存
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/daa0bffc3dbf499f6b4f3d079574276e.png" width="70%"/>

    • 查看已跟踪的文件中哪些暂存需要提交:

      git add ./  # 将文件添加到暂存区
      git diff --cached  # 查看哪些暂存需要提交
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/42713540b7ad165404f6aac5dbc885f1.png" width="70%"/>

  4. 查看提交记录

    • 详细显示提交记录:

      git log  # 查看提交记录(包含提交对象hash值、提交者、时间等)
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/12/1e50ae7b98cf79d353fd025454dde38d.png" width="70%"/>

      注意:如果内容过多,可以按上下键翻页查看,按q键退出

    • 单行显示提交记录:

      git log  --oneline  # 单行显示每条提交记录
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/12/ed01922eac40dd72b8d55913bf84fa71.png" width="70%"/>

    • 显示提交记录:

      git log --oneline --decorate --graph --all
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/b3dd617dfd34aa2d668301e444f4197f.png" width="70%"/>

删除文件

  1. 定义:将某个文件从工作区中删除

  2. 案例1:使用rm命令删除laofu.txt文件后再使用 git status 命令查看文件状态

    rm -rf laofu.txt  # 删除文件
    ls  # 查看文件目录
    git status  # 查看文件状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/29a5ecad4f1d81928195e09adc4f7d88.png" width="70%"/>

    git add ./  # 将修改加入暂存区
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/f522386f888cdb2a3570e441bdc3ff7e.png" width="70%"/>

  3. 案例2:使用 git rm 命令删除已跟踪的文件,比较与rm的区别

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/12/3c37641eb837bd427263f30c09eeff26.png" width="70%"/>

  4. 比较 git rmrmgit rmrm -rf + git add 作用相同

修改文件

  1. 定义:将工作区文件重命名后添加到暂存区

  2. 案例1:将laoliu.txt重命名为laoliuliu.txt后将其添加到暂存区,查看文件状态

    mv laoliu.txt laoliuliu.txt  # 文件重命名
    git status  # 查看重命名后的文件状态
    git add ./  # 将改名后的文件添加到暂存区
    git status  # 查看重新添加到暂存区后文件的状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/11/f993a6db0b4758741708769f154b4da2.png" width="70%"/>

  3. 案例2:使用 git mv 命令重命名已跟踪的文件,比较与mv的区别

    git mv test.txt tests.txt  # 文件重命名
    git status  # 查看文件状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/12/798d7306f9f8c5da27e33d92b5198aa7.png" width="70%"/>

  4. 比较 git mvmvgit mvmv + git add 作用相同

git分支操作

创建分支

  1. 语法:

    git branch 分支名  # 在当前分支创建分支
    git branch 分支名 提交对象  # 创建分支并指向某个提交对象
    
  2. 案例1:创建一个名为damu的分支

    git branch damu
    git log --oneline  # 查看当前分支
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/bb429d154021a4dae7dbbdd624600541.png" width="70%"/>

    注意:HEAD所指向的分支就是当前所在分支

  3. 案例2:在hash值为e319357的提交对象上创建dev分支

    git branch dev e319357  # 创建名为dev的分支,指向提交对象e319357
    git log --oneline  # 查看当前分支信息
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/c822953443f6345c5874899f6615973d.png" width="70%"/>

    创建dev分支后,工作区并没有dev分支对应的文件:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/517ca86544b2435fdecb97d414dfb90e.png" width="70%"/>

    注意:想要在工作区显示某个分支的文件,就要将当前分支切换到该分支

切换分支

  1. 用途:当想给项目添加一个新功能时,就可以新建一个分支

    • 对新分支代码满意:将新分支合并到master分支,从而在项目中添加该新功能
    • 对新分支代码不满意:回退到master分支
  2. 语法:

    git checkout 分支名  # 切换分支
    git checkout -b 分支名  # 创建并切换到该分支
    

    注意:

    • 每次切换分支之前,都要保证当前分支是干净的(git status看一下,防止分支被污染)
    • 切换分支会改变HEAD、暂存区、工作区(版本库内容不会改变,只会无限的增多)
  3. 案例:切换当前分支到dev分支,并显示工作区文件目录

    git log --oneline  # 查看当前分支信息
    git checkout dev  # 切换分支为dev
    ll  # 查看工作区文件目录
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/cf0b182d490cef019ae1f602df5f0cfe.png" width="70%"/>

    分支切换到dev后,由于master分支在dev分支的后面,导致使用 git log 命令无法显示:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/18c420cae3d9be800a5e47e4d4d9b5c5.png" width="70%"/>

    可以使用 git log --oneline --decorate --graph --all 显示完整分支信息:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/ab461e1b4089c8c995b0d54603dc6748.png" width="70%"/>

删除分支

  1. 语法:

    git branch -D 分支名  # 删除指定分支
    

    注意:若要删除的分支为当前所在分支则必须先切换到其它分支,不可以自己删自己

  2. 案例:删除分支dev

    git log --oneline  # 查看当前分支
    git checkout master  # 切换分支到master
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/5803fdb4753198d6f394fee039bcccd0.png" width="70%"/>

    注意:切换到其它分支前要保证分支干净,但上图未做判断(git status)

    git log --oneline  # 再次查看当前分支
    

git branch -D dev # 删除dev分支


运行结果:

<img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/d6c01be3bc0bd254bc1e19f487514fa9.png" width="70%"/>

注意:其实删除分支的参数是 `-d` ,`-D` 是强制删除某个分支

## 查看分支

1. 语法:

```git
git log --oneline  # 查看当前分支
git branch  # 打印分支列表
git branch -v  # 查看每个分支最后的提交信息(git log也能查看,但不够直观)
  1. 案例:

    • 查看当前所在分支:

      git log --oneline  # 查看当前分支
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/664a95793e6a25c00eab9a718e55da5d.png" width="70%"/>

      注意:HEAD所指向的分支就是当前所在分支

    • 打印分支列表:

      git branch  # 打印分支列表
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/a4d19cb106dbc31968695464724ef297.png" width="70%"/>

    • 查看每个分支最后的提交信息:

      git branch -v  # 显示每个分支最后的提交信息
      git log --oneline  # 显示当前版本信息
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/07b01952600ec6b2fc7bb716baff1979.png" width="70%"/>

合并分支

  1. 语法:

    git merge 分支名  # 将当前分支与某分支合并
    
  2. 案例1:将damu分支合并到master分支(快速合并)

    git log --oneline  # 查看当前分支
    git status  # 查看文件状态
    git checkout master  # 切换到master分支
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/406ed5e25d265d4c2252c82df07bfe14.png" width="70%"/>

    git merge damu  # 将damu分支合并到master分支
    git log --oneline  # 再次查看当前分支
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/e8b406fbc1feb9439539f2b0da9cf503.png" width="70%"/>

  3. 案例2:模拟并解决合并冲突(典型合并)

    git checkout -b "ct-test"  # 创建并切换到新分支
    ll  # 查看文件目录
    vim a.txt  # 修改a.txt
    git add ./
    git commit -m "2 commit for a.txt v2 for ct-test"
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/92e55443f5f28aac357aa2e433f43000.png" width="70%"/>

    git status  # 切换分支前,确保分支干净
    git checkout master  # 切换分支到master
    vim a.txt  # 修改a.txt
    git commit -am "3 commit for a.txt v2 for master"
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/b58ba0a21a3ab09eda16e670c126ac54.png" width="70%"/>

    git merge ct-test  # 将ct-test分支合并到master
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/8811d1f4a063e949d3fa9bd481fa96dd.png" width="70%"/>

    注意:上图中能看到是a.txt文件冲突

    vim a.txt  # 查看冲突的文件
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/837e036a8a30a66f8e735ebadba55110.png" width="70%"/>

    git add ./  # 告知git冲突已经解决
    git commit -m "4 commit for fix ct"
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/d733fed59b0a92eae8a05a270dbbb433.png" width="70%"/>

其它内容

  1. 分支模式

    • 长期分支:master
    • 特性分支:要实现某个功能而开的分支
  2. 分支本质:提交对象

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/9e1041d70455ddc5600677b44a77cf28.png" width="70%"/>

    注意:每次提交后,分支对应的提交对象都会改变

  3. 分支原理:

    • HEAD:存放其指向的分支名

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/13/e6ed5bc9be8a5f6726d5ac3a18fedba2.png" width="70%"/>

    • .git/refs/heads:存放该分支对应的提交对象

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/a43db9b9ddb20112a164220b78ef8192.png" width="70%"/>

      注意:项目中的所有分支都会被存放在.git/refs/heads/master目录下

  4. 配别名:

    • 将命令git status配别名为git st:

      git config --global alias.st "status"  # 总结配别名的规律
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/80ebcc5dd8487dccee9d9a7e1f3f2b3b.png" width="70%"/>

      注意:当双引号中只有一个单词时,可将双引号省略

    • 将命令 git log --oneline --decorate --graph --all 配别名为 git lol:

      git config --global alias.lol "log --oneline --decorate --graph --all"
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/a235bdb2d4aa5130177ab33dea37128e.png" width="70%"/>

git存储

  1. 应用场景:要切换到其它分支,但当前分支的工作还没有完成,就可以利用git存储

  2. 语法:

    git stash list  # 查看当前分支下存储栈内容
    git stash  # 保存存储,将当前分支文件存入栈中
    git stash pop  # 应用栈顶存储,并将栈顶元素删除
    git stash apply  # 仅应用栈顶存储
    git stash drop 元素名称  # 仅删除栈中指定存储
    

    注意:

    • 存储后当前分支会变成干净的分支,可以切换到其它分支(其本质还是做了一次提交,只是不计入log)
    • 栈中一般只存储一次,否则操作会很复杂
  3. 案例:在damu分支中修改a.txt文件,存储damu分支后切换到master分支,再切换到damu分支并恢复修改

    git branch  # 查看当前所在分支
    vim a.txt  # 修改a.txt内容
    git status  # 查看文件状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/5ca3977c91de7789cd27fd0689a0f275.png" width="70%"/>

    注意:当前分支不干净,不能直接切换到master分支

    git stash  # 通过存储当前分支文件,将当前分支变为干净分支
    git stash list # 查看存储栈
    git status  # 查看文件状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/39b31539475b5f27b6b6525f2ede9f42.png" width="70%"/>

    git checkout master  # 切换分支到master
    git checkout damu  # 切换分支到damu
    git stash list  # 查看当前分支存储内容
    git stash pop  # 应用栈顶存储,并删除栈顶内容
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/d4a8db15f483972cbf6bad529803bf7d.png" width="70%"/>

git后悔药

工作区

撤销修改

  1. 语法:

    git checkout --文件名  # 撤销修改
    
  2. 案例:master分支下修改a.txt文件后撤销修改

    git status  # 查看文件状态
    git checkout -- a.txt  # 撤销修改
    git status  # 再次查看文件状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/824793fa8ec149ff32a2f8a8338dff4c.png" width="70%"/>

    注意:git只能撤销已跟踪的文件

暂存区

撤销暂存

  1. 语法:

    git restore --staged 文件名  # 撤销暂存
    
  2. 案例:修改a.txt内容并将其添加到暂存区后撤销暂存

    vim a.txt  # 修改文件内容
    git add ./  # 将文件添加到暂存区
    git status  # 查看文件状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/e74d2d67fdeb72721e0eaff317d881d4.png" width="70%"/>

    git restore --staged a.txt  # 撤销暂存
    git status  # 查看文件状态
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/cbe222cba47dc4aa76792ad6fd0213de.png" width="70%"/>

版本库

撤销提交

  1. 场景:提交后发现注释错误,需要修改注释

  2. 语法:

    git commit --amend  # 撤销提交
    
  3. 案例1:提交a.txt后修改注释内容

    git commit -m "1 commit for a.txt v5"  # 提交到版本库
    git lol  # 查看注释
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/8862b0a1d910ff17cee9c7ef834a6229.png" width="70%"/>

    git commit --amend  # 撤销提交(修改注释)
    git lol  # 查看注释
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/14/4657f4c5ba2d506e380b5c27f372c397.png" width="70%"/>

  4. 案例2:修改a.txt并将其提交到版本库,修改版本库中a.txt的内容

    vim a.txt  # 修改a.txt文件内容
    git st  # 查看文件状态
    git commit -am "1 commit for a.txt v6 50%"  # 提交到版本库
    git lol  # 查看版本内容
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/c0363707db7f7cbd4ee277e519d7e687.png" width="70%"/>

    vim a.txt  # 再次修改a.txt文件内容
    git st  # 查看文件状态
    git add ./  # 将修改后的a.txt文件添加到暂存区
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/29927e54ab1c7a3de2c34a3401f8e82d.png" width="70%"/>

    注意区分:

    • 若执行:git commit --amend

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/261f6e6b9df4c4c48c5e5dd9bfa090ee.png" width="70%"/>

    • 若执行:git commit -m “1 commit for a.txt v6 50%”

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/e317849c387da4db17c46cb364affb58.png" width="70%"/>

    总结:

    • 使用 git commit --amend 命令会覆盖上次提交
    • 使用 git commit -m "" 命令提交与上次提交没有关系

reset三部曲

reset命令

  1. 作用:通过移动HEAD来实现版本回退

  2. HEAD移动图示:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/aac63b8ad30816debca341a82a76f5d8.png" width="70%"/>

    注意:HEAD会带着分支移动,要与checkout(切换分支)区分开

  3. 参数:

    • --soft:只更新版本库内容
    • --mixed:更新版本库、暂存区内容
    • --hard:更新版本库、暂存区内容

--soft

  1. 语法:

    git reset --soft HEAD~【提交对象】  # 版本回退,并更新版本库内容;HEAD~表示上一次提交,也可使用提交对象
    
  2. 案例:切换file.txt到上一次提交版本

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/10fb19ded6c63a0e2b71877fef774e2f.png" width="70%"/>

    git lol  # 查看当前版本
    git reset --soft HEAD~  # 切换版本
    git lol  # 再次查看当前版本
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/644813827737cd93ddf96995916a5a79.png" width="70%"/>

    cat file.txt  # 查看工作区内容
    git ls-file -s
    git cat-file -p git对象  # 查看暂存区内容
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/cbbf5fd88bcbfed4a5ca1acc2ecb7a21.png" width="70%"/>

    总结:--soft参数只会更新版本库内容,不会更新暂存区、工作区内容

--mixed

  1. 语法:

    git reset 【--mixed】 HEAD~【提交对象】  # 版本回退,并更新版本库、暂存区内容
    
  2. 案例:切换file.txt到最后一次提交版本

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/282d84cf2239ab82de14285c5426e89f.png" width="70%"/>

    git reflog  # 查看第三次提交的提交对象(git reflog能显示全部提交版本)
    git reset --mixed 提交对象  # 切换到最后一次提交
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/0396143a8c059767da7fce7cd8b428cc.png" width="70%"/>

    git lol  # 查看版本库变化
    git ls-files -s
    git cat-file -p  git对象# 查看暂存区变化
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/3a1627ae3ae676e800754aa661deaf3e.png" width="70%"/>

    总结:--mixed参数会更新版本库、暂存区内容,不会更新工作区内容

--hard

  1. 语法:

    git reset --hard HEAD~【提交对象】  # 版本回退,并更新版本库、暂存区、工作区内容
    
  2. 案例:切换file.txt到上一次提交版本

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/10fb19ded6c63a0e2b71877fef774e2f.png" width="70%"/>

    git reset --hard HEAD~  # 切换到上次提交
    cat file.txt  # 查看工作区变化
    git lol  # 查看版本库变化
    git ls-files -s
    git cat-file -p git对象  # 查看暂存区变化运行结果:
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/786e471c840b046df2c1564a6f62a712.png" width="70%"/>

    总结:--hard参数会更新版本库、暂存区、工作区内容

  3. 区分checkout:

    • checkout只动HEAD,--hard动HEAD而且带着当前分支一起走
    • checkout对工作目录是安全的,--hard是强制覆盖工作目录

打tag

标签列表

  1. 标签用途:想要发布项目的1.0.0版本,就可以打一个v1.0.0的标签(版本号)

  2. 语法:

    git tag  # 列出所有标签
    git tag -l "1.1.0*"  # 列出所有1.1.0以后的版本
    

创建标签

  1. 语法:

    git tag v1.0.0  # 创建标签
    git tag v1.0.0 提交对象  # 给指定提交对象创建标签
    
  2. 案例:创建一个v1.0的标签

    git tag v1.0  # 创建标签
    git lol  # 查看标签
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/ebfe3e4e3b0330d23c2910d79eaa3267.png" width="70%"/>

    注意:创建新的提交后,tag位置不会随HEAD

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/269f37b07ef2e1af2e162278fe672dcb.png" width="70%"/>

查看标签

  1. 语法:

    git show v1.0  # 查看指定标签
    
  2. 案例:查看标签v1.0

    git show v1.0
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/b9a6aecbe7bfbc957e100560cbbe7686.png" width="70%"/>

删除标签

  1. 语法:

    git tag -d 标签名  # 删除指定标签
    
  2. 案例:给第一次提交打标签v1.0

    git tag -d v1.0  # 删除原来的v1.0标签
    git lol  # 查看第一次提交的commitHash
    git tag v1.0 提交对象  # 给指定提交对象打v1.0标签
    git lol  # 查看版本日志
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/4e9e4b4dce95a0a98e651632cc796926.png" width="70%"/>

检出标签

  1. 用途:想查看、修改某个版本的文件内容

  2. 语法:

    git checkout "标签号"  # 先切换到指定标签
    git checkout -b "标签号"  # 再给当前标签创建分支
    

    注意:如果仅执行 git checkout "标签号" 这个命令,会导致git处于“头”,“身”分离的状态

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/15/9a7ae972a5dc838c169c84d5e3cb98bb.png" width="70%"/>

远程仓库

项目经理

  1. 创建远程仓库

    • 登录github,点击右上角“+”,选择New repository:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20s/4a32d3cefccb42c49614a17eead03dd1.png" width="70%"/>

    • 输入仓库信息:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/5bbc1a676aac1e96227279f0362d1938.png" width="70%"/>

    • 创建完成:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/6669578757574e9cc34e1692f5bba316.png" width="70%"/>

  2. 创建工作目录

    • 新建空白文件夹:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/f7d5172cde930a15e0ffde9a6f9d45ad.png" width="70%"/>

    • 输入命令,初始化仓库:

      git init  # 初始化仓库
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/4ba47bb21287d883ec2c37881aa0b35c.png" width="70%"/>

  3. 为远程仓库配置别名、用户信息

    • 为远程仓库配置别名:

      git remote -v  # 显示远程仓库别名和对应url
      git remote add 别名 url  # 添加一个新的远程仓库同时指定一个别名
      git remote rename 别名 新别名  # 重命名远程仓库
      git remote rm 别名  # 删除某个远程仓库
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/148d73882b9dfd560c1a7b90dfd70bb1.png" width="70%"/>

    • 配置用户信息:

      git config --list  # 查看配置信息
      git config --global user.name "XJHui"
      git config --global user.email "admin@mail.plushine.cn"
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/2d806465fcf124bc1d203a6bf9e37457.png" width="70%"/>

    • 删除配置信息:

      git config --list  # 查看配置信息
      git config --global --unset user.name  # 删除配置信息
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/99b3ad8b2a632cea5ad6212614e2caab.png" width="70%"/>

  4. 推送本地项目到远程仓库

    • 创建文件,提交到版本库:

      echo "damu.txt v1" > damu.txt
      git add ./
      git commit -m "1 commit for damu.txt v1 from taobao"
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/fb48dfbd2a9125cabc4eda1d50853137.png" width="70%"/>

    • 将版本库内容推送到远程仓库:

      git lol  # 查看版本库
      git push 别名 分支名  # 将版本库内容推送到远程仓库
      

      运行结果:(下图提到的用户名和密码是github的用户名和密码,非git中所配置的用户信息)

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/1a4669a4dd18b7a5cb6fb6680b88d329.png" width="70%"/>

      推送成功:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/73eb996c61ba4a073a9ace06cecb587b.png" width="70%"/>

  5. 邀请成员

    • 进入项目设置-》Settings-》Manage access-》Invite a collaborator:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/ff858bb201e3570aac34770201c8be66.png" width="70%"/>

    • 输入用户名,搜索成员:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/31a9d842cae640567d6566ce54a951c3.png" width="70%"/>

    • 等待成员同意邀请:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/9fd64d180787eb29e543520f7c4794ba.png" width="70%"/>

      成员访问邀请链接:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/13333eed5ad92caf6b9643fde80ed65a.png" width="70%"/>

成员操作

  1. 克隆仓库到本地

    • 创建文件夹,克隆项目:

      git clone url  # 克隆远程仓库
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/3f24cc526f8e84b67c7d8780ed438c82.png" width="70%"/>

      注意:

      • 克隆后会生成一个与远程仓库同名的文件夹存放项目文件
      • 成员克隆项目前不需要执行 git init 命令
    • 查看克隆的项目:

      cd git-study  # 进入文件夹
      ll  # 查看文件目录
      cat damu.txt  # 查看文件内容
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/41282e2bd345204661e404358f9abbbb.png" width="70%"/>

    • 查看项目默认别名:

      git remote -v
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/2a63976fd3892f7c86b8383911755507.png" width="70%"/>

      注意:克隆下来的仓库别名默认为origin

  2. 修改文件,推送提交:

    echo "plushine.txt v1" > plushine.txt  # 新建文件
    git add ./
    git commit -m "2 commit for plushine.cn v1 from plushine"
    git push origin master  # 推送到远程仓库
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/9adcbb6b5aff7c6c50d979855e5a9437.png" width="70%"/>

  3. 补充:本地分支、远程分支、跟踪分支(远程跟踪分支,本地分支和远程分支之间的媒介)

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/07b3b2a9a613eb6b3bfebca6cdce147a.png" width="70%"/>

更新内容

  1. 场景:当团队中其它成员向远程仓库中提交了新的代码,就需要将自己电脑上的内容更新

  2. 案例:更新项目经理电脑上的内容

    ll  # 查看文件列表
    git remote -v  # 查看别名
    git fetch 别名  # 内容会更新到跟踪分支上
    ll  # 再次查看文件列表
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/8df2c4f0ead892c9a676384d68ca0c2c.png" width="70%"/>

    git status  # 切换分支前保证分支干净
    git checkout  跟踪分支  # 切换当前分支到跟踪分支
    ll  # 查看文件目录
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/16/3da90e668764ee73a3b075caf3003c84.png" width="70%"/>

    git checkout master  # 切换分支到master
    git merge taobao/master  # 将跟踪分支内容合并到本地分支
    ls  # 查看文件目录
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/44e3afeccce79bdc16049910ec615b8e.png" width="70%"/>

push和pull

  1. 如果本地分支跟踪了远程跟踪分支就可以直接使用git push和git pull命令上传和拉取文件,否则:

    • 上传:git push 别名 分支名
    • 拉取:git fetch 别名,git merge 远程跟踪分支
  2. 判断是否跟踪:

    git branch -vv  # 查看本地分支是否跟踪远程跟踪分支
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/17/b59cc19f61a9cac41922519452f41c4a.png" width="70%"/>

    注意:上图中存在联系即代表已跟踪,不存在联系代表未跟踪

  3. 如何让本地分支跟踪远程跟踪分支

    • clone仓库时本地分支会自动跟踪远程跟踪分支(成员可直接执行 git push 和 git pull 命令)

    • 在新建分支时,可以让本地分支跟踪指定的远程跟踪分支:

      git checkout -b 本地分支名 跟踪分支名  # 新建本地分支,并让本地分支跟踪远程跟踪分支
      git checkout --track 远程跟踪分支名  # 新建与远程跟踪分支同名的本地分支,并让本地分支跟踪远程跟踪分支
      

      注意:存在远程跟踪分支时才能使用该命令,可以使用 git fetch 命令生成远程跟踪分支

    • 让已存在的本地分支跟踪远程跟踪分支:

      git branch -u 远程分支名
      

      注意:同时存在本地分支、远程跟踪分支时才能使用该命令(git lol判断是否存在)

  4. 案例:a、b两个文件夹分别代表团队项目经理和成员,模拟使用 git pull 和 git push 命令

    • a中创建分支zdy和文件zdy.txt:

      git checkout -b zdy  # 创建并切换到新分支
      echo 'zdy.txt v1' > zdy.txt
      git add ./
      git commit -m "2 commit for zdy.txt v1 from a"
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/17/a7205c0dc2d735321d0efdb6804b02f6.png" width="70%"/>

      git push  # 上传分支
      git push git-study zdy  # 上传分支
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/17/0fcf262b22fa35903d869ea4955a4e02.png" width="70%"/>

      注意:

      • 新分支要用 git push 别名 分支名 上传,git branch -u 也无法创建联系,因为没有远程跟踪分支
      • 执行命令 git push git-study zdy 后,git会自动创建远程跟踪分支,但本地分支并不会自动跟踪它
    • b从仓库获取zdy分支并修改zdy.txt文件:

      git pull  # 成员b克隆仓库代码后本地分支会自动跟踪远程跟踪分支,所以可以使用git pull命令
      git lol
      git checkout --track origin/zdy  # b中创建zdy本地分支,并跟踪远程跟踪分支
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/17/85c0f8cd4cf51b079f476e30f699dee4.png" width="70%"/>

      vim zdy.txt
      git add ./
      git commit -m "3 commit for zdy.txt v2 from b"
      git push  # 上传修改
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/17/47726a2e4009a1e5a8eb2f47db2fccef.png" width="70%"/>

    • a再次获取zdy分支内容:

      git pull # 拉取仓库
      git branch -u git-study/zdy  # 让本地分支跟踪远程跟踪分支
      git pull # 拉取仓库
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/17/08a2e7f14a6e19eda00114d4a195bfa5.png" width="70%"/>

      cat zdy.txt
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/17/5b0affa4709cd7b1c4a01f9e594b781d.png" width="70%"/>

远程冲突

  1. 冲突场合:本地操作(典型合并)、远程协作(push、pull)

  2. 案例1:模拟并解决push冲突(a为项目经理,b为团队成员)

    • 仓库内容:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/50502ede9b9179101c33170d9e3e2194.png" width="70%"/>

    • a中修改a.txt并push到远程仓库:

      vim a.txt
      

    git add ./
    git commit -m "2 commit for a.txt v2 from a"
    git push git-study master # 本地分支未跟踪远程跟踪分支,不能使用git push命令

    
    运行结果:
    
    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/8a17ccf11ef63255ecfdacaf17478159.png" width="70%"/>
    
    - b也修改a.txt并push到远程仓库:
    
    ```git
    vim a.txt
    git add ./
    git commit -m "2 commit for a.txt v2 from b"
    git push
    

    运行结果:

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/c48921087011dd60a0fb166fb9071235.png" width="70%"/>

    上图提示:当前推送所修改的内容在仓库已经做了修改,可以先git pull 拉取仓库内容,解决冲突后重新推送

    • b中拉取仓库内容:

      git pull
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/18ee1ad044bd642109760718871645ff.png" width="70%"/>

      vim a.txt  # 修改冲突
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/3a49bcf6d7004f792887029112bdb16a.png" width="70%"/>

      git add ./  # 告知git冲突已经解决
      git commit -m "4 commit for fix a.txt conflict"
      git push  # 再次推送
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/caf8e88179668b12f92de536eaca98b0.png" width="70%"/>

  3. 案例2:模拟并解决pull冲突(a为项目经理,b为团队成员)

    • 在案例1基础上,a拉取仓库内容:

      git branch -u git-study/master  # 本地分支跟踪远程跟踪分支
      git pull  # 拉取仓库内容
      cat a.txt  # 查看文件内容
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/3ac11d2d7916f82b9c79788907aeede7.png" width="70%"/>

    • a中修改a.txt文件并推送到远程仓库:

      vim a.txt
      git add ./
      git commit -m "5 commit for a.txt v3 from a"
      git push
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/839a5be097bd759ab81dea5093e08356.png" width="70%"/>

    • b中修改a.txt文件,提交后使用git pull命令拉取仓库内容:

      vim a.txt
      git add ./
      git commit -m "6 commit for a.txt v3 from b"
      git pull
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18/25eaea18f733e46817f6ab31ef1dabf6.png" width="70%"/>

      vim a.txt  # 解决冲突
      git add ./  # 告知git冲突已解决
      git commit -m "7 commit for fix a.txt conflict"
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/18s/02bb3fa9505eac5afce2f1b0343d1dbd.png" width="70%"/>

Pull Request

  1. 场景:当你想要参与修改某个项目,但没有推送权限,这时可以对这个项目进行“派生”(fork,在你的github空间中创建一个完全属于你的项目副本),将自己的修改提交到派生出的项目副本中并创建PR(Pull Request)请求,项目所有者审核同意后你所修改的内容就会进入源版本库。

    <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/9794bf4db48b3d7d240b12386f4bb1f5.png" width="70%"/>

  2. 基本流程:

    • fork项目,clone副本项目到工作区
    • 修改文件,push到仓库,创建PR
    • 项目所有者审核,提交成功(失败)
  3. 案例:模拟使用PR(xingjiahui:项目创建者,PluShine:无推送权限但想参与修改)

    • fork项目:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/debc4135857a8b6287803a349052b6cf.png" width="70%"/>

      fork后PluShine新增了项目副本仓库:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/509a93468baf97492e0cd4dfe02630b9.png" width="70%"/>

    • 克隆副本仓库,push修改内容:

      git clone https://github.com/PluShine/git-study.git
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/9acaebc2fb45590dc2a33e5e0219e209.png" width="70%"/>

      vim a.txt
      git add ./
      git commit -m "7 commit for a.txt bug fix from PluShine"
      git push
      

      运行结果:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/e0275809c644a9e846adb5a3b95cb1e3.png" width="70%"/>

      进入仓库,创建Pull Request:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/021c15f6aed14a23762f656cdcbc07e2.png" width="70%"/>

      PR创建成功:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/142b2d78e15f1b5f7ee8280afca137bf.png" width="70%"/>

    • 项目创建者审核PR:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/5fa0c508f3932f5e8aa78b61f015daf2.png" width="70%"/>

      合并提交:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/19s/fec3aeef440196c28e5ba879291bf4f1.png" width="70%"/>

      合并成功:

      <img src="https://cdn.jsdelivr.net/gh/xingjiahui/CDN@latest/2020/11/20/253e3ed5b05528e3a32168c6ba3eb62e.png" width="70%"/>


不足之处,欢迎留言,会及时回复,及时更正!

创作不易,感谢支持!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • 1. 前言 2. 为什么使用Git 3. 为什么使用命令行 4. 安装 5. 配置5.1. 用户信息5.2. 文本...
    科研者阅读 1,480评论 0 1
  • 初识git git官网 作者简介 作者:林纳斯·托瓦兹(Linus Benedict Torvalds, 1969...
    冷若秋枫阅读 250评论 0 1
  • Git介绍及基本概念 分布式版本控制系统 Git是一个分布式版本控制系统,每个本地保留远程仓库的完整副本,在本地可...
    健四郎阅读 294评论 0 0
  • GIT教程 原创者:文思 一、Git基础 1、认识GIT 有了SVN为何还用GIT? SVN增量式管理,GIT采...
    文思li阅读 2,575评论 0 0
  • Git 与 SVN 区别 Git不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。如果你是一...
    心至靜行至遠阅读 701评论 0 5