Git的用法

简介

Git是一款免费、开源的分布式版本控制系统,方便相互协作开发。

安装

我主要的环境是windows,所以在介绍在Windows上安装Git,我们只需要百度Git for Windows,然后点击下载,安装后,桌面会有Git BASH和Git GUI。

Git BASH
Git for Windows提供了用于从命令行运行Git的BASH仿真。* NIX用户应该感觉到在家里,
因为BASH仿真的行为就像LINUX和UNIX环境中的“git”命令。

Git GUI
由于Windows用户通常期望图形用户界面,Git for Windows还提供了Git GUI,
它是Git BASH的强大替代品,
提供了几乎所有Git命令行功能的图形化版本,以及全面的视觉差异工具

配置Git用户信息

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。要检查已有的配置信息,可以使用 git config --list 命令

这两条配置很重要,每次 Git 提交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录,如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或者电邮,只要去掉--global 选项重新配置即可,新的设定保存在当前项目的.git/config 文件里。

创建版本库

版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”

在电脑的任何地方,创建一个空的文件夹,然后cd到文件夹,pwd显示当前目录
*(备注:使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。)*,
通过git init命令把这个目录变成Git可以管理的仓库
$ git init
Initialized empty Git repository in 你的pwd
瞬间Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

如果你没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -ah命令就可以看见

仓库的提交

image.png

根据上面的图片,下面给出了每个部分的简要说明:

Directory:使用Git管理的一个目录,也就是一个仓库,包含我们的工作空间和Git的管理空间。
WorkSpace:需要通过Git进行版本控制的目录和文件,这些目录和文件组成了工作空间。
.git:存放Git管理信息的目录,初始化仓库的时候自动创建。
Index/Stage:暂存区,或者叫待提交更新区,在提交进入repo之前,我们可以把所有的更新放在暂存区。
Local Repo:本地仓库,一个存放在本地的版本库;HEAD会只是当前的开发分支(branch)。
Stash:是一个工作状态保存栈,用于保存/恢复WorkSpace中的临时状态。

First:我们需要先打要提交的文件,放入工作空间--把文件放入建立仓库的文件夹
Second: 用命令git add告诉Git,把文件添加到仓库
Last:用命令git commit告诉Git,把文件提交到仓库
备注:解释一下git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,
当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
当然文件的编码最好选择utf-8

查看仓库的更新

  • 通过git status可以查看WorkSpace的状态
  • 通过git diff用于显示WorkSpace中的文件和暂存区文件的差异
  • 通过git log命令显示从最近到最远的提交日志(备注:如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline,这样就只有commit id(版本号)和改动内容
  • 通过git reflog命令会显示,记录这个仓库中所有的分支的所有更新记录,包括已经撤销的更新

对仓库进行撤回

根据前面对基本概念的了解,更新可能存在三个地方,WorkSpace中,Stage中和repo中。下面就分别介绍一下怎么撤销这些更新

使用"git checkout --<file>..."来撤销WorkSpace中的更新
(备注:使用这种方法撤销更新的时候一定要慎重,因为通过这种方式撤销后,
更新将没有办法再找回)
通过"git reset HEAD <file>..."把暂存区的更新移出到WorkSpace中
使用命令git reset --hard commit_id或者git reset --hard HEAD^,用来指向repo中想要的版本。
(备注:使用HEAD指针或者使用commit id

HEAD指针指向当前分支中的版本。上一个版本就是HEAD^,
上上一个版本就是HEAD^^如果想回退到更早的提交,可以使用"HEAD~n"。
(也就是,HEAD^=HEAD~1,HEAD^^=HEAD~2))

commit id(版本号)是一个SHA1计算出来的一个非常大的数字,用十六进制表示,
版本号没必要写全,前几位就可以了,Git会自动去找。
当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了

--hard和--soft

前面在使用reset来撤销更新的时候,我们都是使用的"--head"选项,其实与之对应的还有一个"--soft"选项,区别如下:

--head:撤销并删除相应的更新
--soft:撤销相应的更新,把这些更新的内容放到Stage中

仓库删除文件

  • 对WorkSpace中的文件进行删除了,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了
  • 现在你有两个选择:
    一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit -m
    另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本 git checkout -- <file>
image.png

远程仓库

  • GitHub账号。由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密,在Github中绑定id_rsa.pub公钥。
创建SSH Key。在用户主目录下,看看有没有.ssh目录,
如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,
如果已经有了,可直接到  Github里面设置。如果没有,打开GitBash,创建SSH Key
$ ssh-keygen -t rsa -C "youremail@example.com"
  • 把自己本地的仓库和Github的开源仓库进行关联
    git remote add origin git@github.com:user_name/Github仓库的名字.git
  • 把本地库的内容推送到远程,用git push命令
    $ git push -u origin master (备注:由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令)
  • 每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改
从远程仓库克隆

1.勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件(.md文件是markdown格式的写法)
用命令git clone克隆一个本地库(path取决于pwd)

Cloning into 'mygit'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

$ cd gitskills
$ ls
README.md
注意把Git库的地址换成你自己的,然后进入mygit目录看看,已经有README.md文件了

Github的分支管理

Git鼓励大量使用分支:

查看分支:git branch

创建分支:git branch <name>

切换分支:git checkout <name>

创建+切换分支:git checkout -b <name>

合并某分支到当前分支:git merge <name>

删除分支:git branch -d <name>
强制删除:git branch -D <name>

有时候分支合并会有冲突git status也可以查看冲突的文件,
我们也可以自己cat查看文件内容
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容
我们找出不同点,进行修改,然后add和commit
用git log --graph命令可以看到分支合并图
通常,合并分支时,如果可能,Git会用Fast forward模式,
但这种模式下,删除分支后,会丢掉分支信息
强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,
这样,从分支历史上就可以看出分支信息
 git merge --no-ff -m "merge with no-ff" dev
备注:因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。
bug分支
$ git checkout -b issue-101  
$ git merge --no-ff -m "merged bug fix 101" issue-101
(备注:修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,最后进行合并)
Git提供了一个stash功能,可以把当前工作现场“储藏”起来
用git stash list命令查看stash内容
一是用git stash apply恢复,但是恢复后,stash内容并不删除,
你需要用git stash drop来删除;
另一种方式是用git stash pop,恢复的同时把stash内容也删了
多人协作
查看远程库的信息用git remote或者用git remote -v显示更详细的信息
推送分支git push origin master/git push origin dev
远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支
要在dev分支上开发,就必须创建远程origin的dev分支到本地
 git checkout -b dev origin/dev

从本地推送分支,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,
本地和远程分支的名称最好一致;

建立本地分支和远程分支的关联,
使用git branch --set-upstream branch-name origin/branch-name;

从远程抓取分支,使用git pull,如果有冲突,要先处理冲突

更新远程代码到本地仓库

理解 fetch 的关键, 是理解 FETCH_HEAD,FETCH_HEAD指的是: 某个branch在服务器上的最新状态’。这个列表保存在 .Git/FETCH_HEAD 文件中, 其中每一行对应于远程服务器的一个分支。

当前分支指向的FETCH_HEAD, 就是这个文件第一行对应的那个分支.

一般来说, 存在两种情况:

  • 如果没有显式的指定远程分支, 则远程分支的master将作为默认的FETCH_HEAD.
  • 如果指定了远程分支, 就将这个远程分支作为FETCH_HEAD.
git fetch origin branch1

这个操作是git pull origin branch1的第一步, 而对应的pull操作,并不会在本地创建新的branch。设定当前分支的FETCH_HEAD为远程服务器的branch1分支。

这个命令可以用来测试远程主机的远程分支branch1是否存在, 如果存在, 返回0, 如果不存在, 返回128, 抛出一个异常.

git fetch origin branch1:branch2

首先执行上面的fetch操作,使用远程branch1分支在本地创建branch2(但不会切换到该分支),如果本地不存在branch2分支, 则会自动创建一个新的branch2分支,

如果本地存在branch2分支, 并且是`fast forward', 则自动合并两个分支, 否则, 会阻止以上操作.

fetch更新本地仓库两种方式:

//方法一
$ git fetch origin master //从远程的origin仓库的master分支下载代码到本地的origin master

$ git log -p master.. origin/master//比较本地的仓库和远程参考的区别

$ git merge origin/master//把远程下载下来的代码合并到本地仓库,远程的和本地的合并

//方法二
$ git fetch origin master:temp //从远程的origin仓库的master分支下载到本地并新建一个分支temp

$ git diff temp//比较master分支和temp分支的不同

$ git merge temp//合并temp分支到master分支

$ git branch -d temp//删除temp

1、git reset

没有push,这种情况发生在你的本地代码仓库,可能你add ,commit 以后发现代码有点问题.

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交commit_id(79f673d631b08907496ce792f429e1f00da25b73),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard 79f673d631b08907496ce792f429e1f00da25b73

  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

2、git revert

已经push,对于已经把代码push到线上仓库,你回退本地代码其实也想同时回退线上代码,回滚到某个指定的版本,线上,线下代码保持一致.你要用到下面的命令

git revert用一个新提交来消除一个历史提交所做的任何修改.

revert 之后你的本地代码会回滚到指定的历史版本,这时你再 git push 既可以把线上的代码更新.(这里不会像reset造成冲突的问题)

revert 使用,需要先找到你想回滚版本唯一的commit标识代码,可以用 git log 或者在adgit搭建的web环境历史提交记录里查看.

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">git revert c011eb3c20ba6fb38cc94fe5a8dda366a3990c61</pre>

3、两者区别

git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit看似达到的效果是一样的,其实完全不同.

第一:上面我们说的如果你已经push到线上代码库, reset 删除指定commit以后,你git push可能导致一大堆冲突(或git push -f强制推送).但是revert 并不会.

第二:如果在日后现有分支和历史分支需要合并的时候,reset 恢复部分的代码依然会出现在历史分支里.但是revert 方向提交的commit 并不会出现在历史分支里.

第三:reset 是在正常的commit历史中,删除了指定的commit,这时 HEAD 是向后移动了,而 revert 是在正常的commit历史中再commit一次,只不过是反向提交,他的 HEAD 是一直向前的.

Git的标签

  • 命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id;命令git tag <name> commit_id
  • 创建带有说明的标签,用-a指定标签名,-m指定说明文字
    git tag -a <name> -m "blablabla..." commit_id
  • 用git show <tagname>查看标签信息
  • 推送某个标签到远程,使用命令 git push origin <tagname>
  • 次性推送全部尚未推送到远程的本地标签 git push origin --tags
  • 命令git tag -d <tagname>可以删除一个本地标签;
  • 命令git push origin :refs/tags/<tagname>可以删除一个远程标签

总结

整体来说,git的功能都是很强大的,我自己写这样一篇git的操作,也是相当于,自己给自己做笔记,方便,自己以后找资料用,同时也可以给予初学者一定的帮助。

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

推荐阅读更多精彩内容