Git 使用原理与常用命令

前言

  在工作中,基本上都是使用Git进行程序版本管理,并且进行多人协同合作开发。但是往往我们并不知道为什么要使用Git,对于那些繁多的git命令也不求甚解,经常一段时间不使用就忘记了,即使记得心里还是虚虚的,担心出错造成代码库崩盘。这一切的根本原因还是在于我们对于git的理解不清晰,虽然可以使用Git版本管理工具,但是在掌握命令行的前提下使用,会更加的得心应手。
  相较于先前的集中式存储SVN,Git采用的是分布式存储,带来的好处就是程序的所有版本都存储在每一台分布式的机器上,并且可以在断网情况下继续编写程序。

Git时间线与多人协作

  Git将每次提交都串成一条时间线,这条时间线就是一个分支。
  Git 作为一个源码管理系统,不可避免涉及到多人协作。协作必须有一个规范的工作流程,让大家有效地合作,使得项目井井有条地发展下去。"工作流程"在英语里,叫做"workflow"或者"flow",原意是水流,比喻项目像水流那样,顺畅、自然地向前流动,不会发生冲击、对撞、甚至漩涡。


Git时间线图解

Git项目库的理解与初始化

  Git项目库怎么理解?其实就是被Git进行管理的文件夹。首先我们要明确的是Git是一个程序版本管理工具,程序的具体实例就是一个文件夹,所以说Git可以进行文件夹内容改动的管理。那么问题就来了,不是什么文件夹都可以被Git管理,我们需要先告诉Git管理哪些文件夹,这个「告诉」的操作就叫做Git项目库初始化,具体操作就是git init

  • git init
      当你在本地新建一个git项目,或者你想把某个文件夹进行Git管理,首先你需要初始化该项目,初始化命令就是git init。完成git项目初始化之后,文件夹内部会多出一个隐藏文件.git(直接打开看不见)。这就是项目的版本库,记载着项目每次提交等信息。

Git项目库的组成

  Git项目库是由两部分组成的:工作区版本库

Git项目库组成

  如上图所示,git项目库主要分为工作区版本库两个部分,工作区指的就是我们原始的文件夹,而版本库是指git init初始化文件夹后新增的.git文件。注意,.git文件对于我们是隐藏的。
  Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,和本地分支(其中Git为我们自动创建第一个分支master),以及指向本地当前分支的一个指针叫HEAD
  这里我们要有一个概念,那就是git在本地项目库中维护了和远程库一样的代码分支,git commit命令事实上是将代码提交到本地维护的代码分支上面,然后接下来在将本地分支同步到远程库的分支上面。
git提交代码图示

版本库.git文件夹内容快照

image.png

工作区与暂存区

git提交代码图示

  我们在提交代码时候,经常先使用git add <filename>将工作区改动的文件添加到暂存区(stage/index),然后使用git commit -m <message>将暂存区的所有改动提交到本地分支,最后再git push origin -u <远程库分支名>将本地分支推送到远程库。
  从上面的三个步骤中,可以看到出现了一些新的概念:暂存区(stage/index)工作区本地分支,下面就来梳理一下这三个概念。

  • 工作区(Working Directory)
    就是你在电脑里能看到的目录,也是你通过IDE直接进行编程的目录,比如我的test文件夹就是一个工作区:

    工作区目录

    注意上图中,存在一个隐藏文件夹.git,这个不算工作区,而是Git的版本库。

  • 版本库(Repository)

    Git项目库组成

    如上面所说,工作区的隐藏文件夹.git不算是工作区,而是Git的版本库。
    Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,和本地分支(其中Git为我们自动创建第一个分支master),以及指向本地当前分支的一个指针叫HEAD

git常用命令汇总

添加远程库

git remote add origin <远程库地址>
当你创建好了一个本地项目之后,你希望将其与远程建立的库连接,从而在每次代码写完后,能够提交到代码托管网站,保证了安全性与结构清晰。其中的origin指的是远程库的名字,一般都默认为origin,也可以修改。但不建议,因为写代码是与人交流合作的工作,不要为了张扬个性让别人很难阅读与理解。

提交代码
  • 提交到暂存区
    git add . 或者 git add <文件名>
  • 提交到本地分支
    git commit -m '<提交说明>'
  • 推送到远程库
    git push -u origin <分支名>
    以上就是提交代码的三板斧,再具体说明之前,首先我们要建立一个git的形象化模型。
    git add

      如上图所示,git项目库主要分为工作区版本库两个部分,工作区指的就是我们原始的文件夹,而版本库是指git init初始化文件夹后新增的.git文件。注意,.git文件对于我们是隐藏的。在版本库中,同样主要分为两个部分:暂存区(stage)本地分支
      这里我们要有一个概念,那就是git在本地项目库中维护了和远程库一样的代码分支,git commit命令事实上是将代码提交到本地维护的代码分支上面,然后接下来在将本地分支同步到远程库的分支上面。
    git提交代码图示

  暂存区的概念,我理解为充当了一个缓冲的作用,创造一个后悔与再三考虑的机会。推荐廖雪峰的git教程,讲的简单清晰明了。

查看当前项目状态

git status
当我们git add .之后,忘记了git commit,第二天不知道代码提交到了哪一步,这个时候git status就可以告诉我们暂存区是否干净,本地代码是否需要git push到远程库中。

克隆远程仓库项目到本地

git clone <远程库地址>
当我们想要下载远程库中的项目代码的时候,并没有一键下载的按钮,反而很容易得到项目远程库的地址。这个地址就是为了git clone这条命令而存在的。新手需要注意的一点是,克隆项目之前,先使用命令行进入你希望下载项目的地址,在使用git clone,不然就不知道克隆的项目在哪,增加了挫败感。
git clone -b [分支名] [远程库地址]
另外还需要注意,使用git clone命令克隆下来的代码默认的是主分支代码(取决于设置的默认分支),需要在本地,使用终端,切换分支命令(git checkout 分支名),才能将代码切换。但人都是懒的,有没有指定克隆的代码分支的命令呢?答案是有的。那就是在git clone -b 后面指定分支名。

拉取远程仓库更新

git pull
当别人提交了代码到主分支的时候,而你的代码还是旧的,这个时候远程库主分支上的代码就比你本地领先了一个版本。前面说的编程是与人合作的工作,你需要在新的项目代码上编写自己的模块。这个时候你就需要git pull拉取远程库最新代码。假设你没有这样做,那么当你git commit代码时,就会报错,说你的代码与远程库发生冲突。所以,提交代码前,git pull一下是很好的习惯。

查看分支

上面说了本地具有代码的所有分支,那么有时候我们需要知道目前所在分支,免得写错了分支,更是麻烦。

  • 查看本地分支
    git branch
  • 查看远程分支
    git branch -r
  • 查看所有分支
    git branch -a

创建新分支并切换

git checkout -b <新建分支名> <基于分支名>

切换分支

git checkout <分支名>

合并分支

git checkout <需要合并分支> 先切换到需要合并其他分支的主要分支上
git merge --no-ff <被合并分支名> 基于当前主要分支,创建新结点,合并其他分支
当我们在自己的开发分支开发结束后,管理员需要将开发者的代码合并到主分支上面。这个过程就叫做合并分支,主要过程分为两步,第一步就是切换到你的主分支(例如master)上,然后git merge你想要合并的分支就可以了。
但是不要放松,这里经常会出错,合并失败,代码冲突。这说明两个分支,在同一处代码做了不同的修改。很想,在某个点,你不同的选择产生了两个截然不同的平行宇宙。这个时候,解决的办法只有一个,查找到冲突的地方,手动修改。

非快进式合并

代码回滚

  这个是另一个很重要的技能,防止你该版本出了重大的错误,或者找不到错误的来源。需要进行时光旅行,将代码重置到上一个版本。
  在此之前,我们需要明确一个概念,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。在版本库中,存在一个HEAD指针,HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点。

HEAD指针

  当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
创建dev分支

清楚了这些,那么接下来就是代码回滚了。
git log -[数字]
每一次提交都有一个自动生成的 commit 标识符,这串标识符就是回滚到具体版本所需要的。上面命令中的数字代表了最近几次的提交日志。
git log -3

git reset --hard [commit序号]
该条命令即可回滚到指定的版本。
git reset --hard HEAD^
该条命令回滚到上一个版本。

提交抵消

最近工作中遇到一种情况,在commit一次代码后,发现这次提交的代码有问题,必须撤销这次commit。如果再手动改回来,首先有点笨,其次难免会有遗漏的地方。
这个时候可以使用git revert,撤销 某次操作,此次操作之前和之后的commit和history都会保留,并且把这次撤销作为一次最新的提交。

 git revert HEAD                  撤销前一次 commit
 git revert HEAD^               撤销前前一次 commit
 git revert <commit> (比如:fa042ce57ebbe5bb9c8db709f719cec2c58ee7ff)
  撤销指定的版本,撤销也会作为一次提交进行保存。
 // 然后推送到origin
 git push origin <分支名>

**git revert 和 git reset的区别 **

  1. git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。
  2. 在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。
  3. git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

参考文章

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

推荐阅读更多精彩内容

  • Git常用语法 [TOC] Git简介 描述 ​ Git(读音为/gɪt/。)是一个开源的分布式版本控制系统,...
    君惜丶阅读 3,502评论 0 13
  • Git是目前最流行的版本管理系统,也是最先进的分布式版本控制系统(distributed version cont...
    pro648阅读 5,688评论 1 17
  • 最近跟闺密讨论,女生到底要不要主动联系男友的问题。 她的男友正处于创业期,特别忙,所以就跟她说,我很忙,如果你想我...
    彤夕云阅读 847评论 3 6
  • (稻盛哲学学习会)打卡第33天 姓名:李晨珂 部门:分水碶 组别:待定 【知~学习】 诵读«活法»切断蛊惑人心的“...
    李晨珂分水碶阅读 202评论 0 0
  • 没有年轮的樹 : 曦 __ 微型散文诗 作者: 何 强 " 发现你不曾有过,也将不会为你所有的一...
    天邊的凝紅阅读 254评论 0 1