Git经常使用功能教程

声明:本文参考廖雪峰老师的Git教程,删除部分我的不经常使用功能作为我的的参考笔记,若是有错漏,欢迎批评我,原文地址是https://www.liaoxuefeng.com/w...git

<!-- TOC -->github

<!-- /TOC -->this

Git简介

Git是分布式版本控制系统,能记录每次对文件的改动加密

clipboard.png

集中式VS分布式

svn是集中式的版本控制系统,必须联网才能工做,版本库集中存放在中央服务器,首先本身从中央服务器取得最新版本,在本地服务器修改后,再把更改推送给中央服务器。记住每次提交前要先进行更新操做,是否有有版本冲突。

clipboard.png

分布式版本控制系统在每一个人本地服务器里都有完整的版本库,能够直接把各自的修改推送给对方,可是分布式版本控制系统一般也有一台充当“中央服务器”的电脑,能够方便交换你们的修改。特别是Git有强大的分支管理。

clipboard.png

安装Git

在Windows上安装Git,直接在Git官网直接下载安装程序而后按默认选项安装便可。
在开始菜单里找到“Git”->“Git Bash”,会弹出一个相似命令行窗口,说明Git安装成功。

clipboard.png

安装完成后,须要设置本地服务器的用户名和Email,在命令行输入:

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

注意git config命令的--global参数,表示本地服务器上全部的Git仓库都会使用这个配置,固然能够给某个仓库指定不一样的用户名和Email

Git命令

建立版本库(仓库repository)

首先建立一个空目录
$ mkdir learngit //新建目录
$ cd learngit //进入这个目录
$ pwd // 显示当前目录
/Users/michael/learngit

初始化这个目录变成Git能够管理的仓库
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/ //仓库成功而且告知是一个空的仓库

当前目录会多一个.git的目录,这个目录是Git用来跟踪管理版本库的,不要手动修改,以避免破坏仓库

注意:图片、视频这些二进制文件,虽然也能由版本控制系统管理,但无法跟踪文件的变化,只能看整体大小的变化,没法知道具体更改部分,Microsoft的Word格式是二进制格式,版本控制系统是无法跟踪Word文件的改动的,若是要真正使用版本控制系统,就要以纯文本方式编写文件

把文件提交到仓库

第一步,把文件添加到仓库
$ git add 文件名

$ git add . //把全部的文件都添加仓库

第二步,把文件提交到仓库
$ git commit -m "本次提交的说明"

为何Git添加文件须要add,commit一共两步呢?下面再解释

工做区和暂存区

工做区(Working Directory)

新建的文件夹learngit就是一个工做区

版本库(Repository)

工做区有一个隐藏目录.git,这个不算工做区,而是Git的版本库。
Git的版本库里存了不少东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为咱们自动建立的第一个分支master,以及指向master的一个指针叫HEAD。

clipboard.png

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的全部内容提交到当前分支。

由于咱们建立Git版本库时,Git自动为咱们建立了惟一一个master分支,因此,如今,git commit就是往master分支上提交更改。

版本回退

查看仓库当前的状态,能够确认有没有须要提交的修改
$ git status

查看修改的内容
$ git diff 文件名

查看提交的日志,输出版本号,做者,日期和提交信息
$ git log

git log加上--pretty=oneline参数就只输出版本号和提交的书面
$ git log --pretty=oneline

把当前版本回退到上一个版本,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,能够写成HEAD~100
$ git reset --hard HEAD^

查看文件内容
$ cat 文件名

查看回退前的版本,查看回退前的日志找回版本号
$ git reset --hard 版本号

Git版本回退速度很快,由于Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD指向更改了。

查看命令的日志,能够找寻到回退前的版本号,从而能够回到回退前的版本
$ git reflog

撤销修改

git checkout -- file能够丢弃工做区的修改:
$ git checkout -- 文件名

命令git checkout -- readme.txt意思就是,把readme.txt文件在工做区的修改所有撤销,这里有两种状况:

一种是readme.txt自修改后尚未被放到暂存区,如今,撤销修改就回到和版本库如出一辙的状态;

一种是readme.txt已经添加到暂存区后,又做了修改,如今,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commit或git add时的状态。
假设你不但改错了东西,还从暂存区提交到了版本库,能够进行版本回退,不过前提是没有推送到远程库。

删除文件

能够直接在文件管理器中把没用的文件删了,或者用rm命令删
$ rm 文件名

要从版本库中删除该文件,那就用命令git rm删掉,而且git commit:
$ git rm 文件名
rm 文件名
$ git commit -m "删除说明"

远程仓库GitHub

关联Git和github

GitHub能够提供Git仓库托管服务,注册一个GitHub帐号,就能够免费得到Git远程仓库。因为你的本地Git仓库和GitHub仓库之间的传输是经过SSH加密的,因此须要设置:

第1步:建立SSH Key。在用户主目录下,看看有没有.ssh目录,若是有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,若是已经有了,可直接跳到下一步。若是没有,打开Shell(Windows下打开Git Bash),建立SSH Key:
$ ssh-keygen -t rsa -C "你的邮箱地址"

一路回车,若是一切顺利的话,能够在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,能够放心地告诉任何人。

第2步:登录GitHub,打开“Account settings”,“SSH Keys”页面:

而后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:

clipboard.png

点“Add Key”,你就应该看到已经添加的Key:

clipboard.png

为何GitHub须要SSH Key呢?由于GitHub须要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,因此,GitHub只要知道了你的公钥,就能够确认只有你本身才能推送。

GitHub容许你添加多个Key。假定你有若干电脑,你一下子在公司提交,一下子在家里提交,只要把每台电脑的Key都添加到GitHub,就能够在每台电脑上往GitHub推送了。

添加远程库

登录GitHub,而后,在右上角找到“Create a new repo”按钮,建立一个新的仓库:

clipboard.png

在Repository name填入learngit,其余保持默认设置,点击“Create repository”按钮,就成功地建立了一个新的Git仓库:

clipboard.png

目前,在GitHub上的这个learngit仓库仍是空的,GitHub告诉咱们,能够从这个仓库克隆出新的仓库,也能够把一个已有的本地仓库与之关联,而后,把本地仓库的内容推送到GitHub仓库。

如今,咱们根据GitHub的提示,在本地的learngit仓库下运行命令:
$ git remote add origin git@github.com:Github帐户名/learngit.git

添加后,远程库的名字就是origin,这是Git默认的叫法。

下一步,就能够把本地库的全部内容推送到远程库上:
$ git push -u origin master

其实是把当前分支master推送到远程。

因为远程库是空的,咱们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在之后的推送或者拉取时就能够简化命令。

推送成功后,能够马上在GitHub页面中看到远程库的内容已经和本地如出一辙,从如今起,只要本地做了提交,就能够经过命令:
$ git push origin master

把本地master分支的最新修改推送至GitHub,如今,你就拥有了真正的分布式版本库!

从远程库克隆

假设咱们从零开发,那么最好的方式是先建立远程库,而后,从远程库克隆。

首先,登录GitHub,建立一个新的仓库,名字叫gitskills:

clipboard.png

咱们勾选Initialize this repository with a README,这样GitHub会自动为咱们建立一个README.md文件。建立完毕后,能够看到README.md文件:

clipboard.png

如今,远程库已经准备好了,下一步是用命令git clone克隆一个本地库
git clone git@github.com:你的GitHub帐号/gitskills.git

GitHub给出的地址不止一个,还能够用https://github.com/michaellia...。实际上,Git支持多种协议,默认的git://使用ssh,但也可使用https等其余协议。

使用https除了速度慢之外,还有个最大的麻烦是每次推送都必须输入口令,可是在某些只开放http端口的公司内部就没法使用ssh协议而只能用https。

使用Git上传文件到GitHub

在须要上传文件的文件夹右键->Git Bash Here打开命令行窗口
在提交代码以前,首先应该检查目前所作的修改
$ git status

检查没有无误后
$ git add . //.表明当前目录下的全部文件都加入暂存区
$ git commit -m "本次提交的说明" //每次提交都应该写清楚说明
$ git pull origin master //将服务器代码同步到本地
$ git push -u origin master
//接着根据提示输入GitHub的用户名和密码

推送成功后,能够马上在GitHub页面中看到远程库的内容已经和本地如出一辙。

若是执行失败,通常是没有将服务器代码同步到本地致使的,先执行上面的git pull命令

分支管理

为何须要分支?

建立一个属于你本身的分支,别人看不到,还继续在原来的分支上正常工做,而你在本身的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工做。

建立和合并分支

首先,咱们建立dev分支,而后切换到dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'

git checkout命令加上-b参数表示建立并切换,至关于如下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'

而后,用git branch命令查看当前分支:
$ git branch

  • dev
    master


git branch命令会列出全部分支,当前分支前面会标一个*号。
而后,咱们就能够在dev分支上正常提交
$ git add readme.txt
$ git commit -m "branch test"
[dev fec145a] branch test
1 file changed, 1 insertion(+)

如今,dev分支的工做完成,咱们就能够切换回master分支:
$ git checkout master
Switched to branch 'master'

切换回master分支后,刚才提交的内容不见了!由于那个提交是在dev分支上,而master分支此刻的提交点并无变:

clipboard.png

如今,咱们把dev分支的工做成果合并到master分支上:
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)

合并完成后,就能够放心地删除dev分支了:
$ git branch -d dev
Deleted branch dev (was fec145a).

删除后,查看branch,就只剩下master分支了:
$ git branch

  • master


由于建立、合并和删除分支很是快,因此Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工做效果是同样的,但过程更安全。

解决冲突

若是master分支和dev分支各自都分别有新的提交,就会出现冲突:

clipboard.png

这种状况下,Git没法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突:

$ git merge feature1

git status告诉咱们冲突的文件:

$ git status

能够直接查看冲突的内容,Git用<<<<<<<,=======,>>>>>>>标记出不一样分支的内容,咱们修改后保存
再提交:
$ git add readme.txt
$ git commit -m "conflict fixed"

如今,master分支和feature1分支变成了下图所示:

clipboard.png

用带参数的git log也能够看到分支的合并状况:
$ git log --graph --pretty=oneline --abbrev-commit

最后,删除feature1分支:
$ git branch -d feature1

当Git没法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。

注意:合并分支时,加上--no-ff参数就能够用普通模式合并,合并后的历史有分支,能看出来曾经作过合并,而fast forward合并就看不出来曾经作过合并。

Bug分支

当手头工做没有完成时,先把工做现场git stash一下,而后去新建分支去修复bug,修复后,切换到master分支在完成合并,最后删除Bug分支,在切换回到dev分支,一是用git stash apply恢复,可是恢复后,stash内容并不删除,你须要用git stash drop来删除;
另外一种方式是用git stash pop,恢复的同时把stash内容也删了,回到工做现场。

feature分支

开发一个新feature,最好新建一个分支;
若是要丢弃一个没有被合并过的分支,能够经过git branch -D <name>强行删除。

标签管理

发布一个版本时,咱们一般先在版本库中打一个标签(tag),这样,就惟一肯定了打标签时刻的版本。未来不管何时,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。因此,标签也是版本库的一个快照。
Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?可是分支能够移动,标签不能移动),因此,建立和删除标签都是瞬间完成的。

Git有commit,为何还要引入tag?

由于版本号很差记~

建立分支

在Git中打标签很是简单,首先,切换到须要打标签的分支上:

$ git branch

  • dev
    master

$ git checkout master
Switched to branch 'master'

而后,敲命令git tag <name>就能够打一个新标签:
$ git tag v1.0

能够用命令git tag查看全部标签:
$ git tag
v1.0

默认标签是打在最新提交的commit上的。有时候,若是忘了打标签,好比,如今已是周五了,但应该在周一打的标签没有打,怎么办?

方法是找到历史提交的commit id,而后打上就能够了:
$ git log --pretty=oneline --abbrev-commit
6a5819e merged bug fix 101
cc17032 fix bug 101
7825a50 merge with no-ff
6224937 add merge
59bc1cb conflict fixed
400b400 & simple
75a857c AND simple
fec145a branch test
d17efd8 remove test.txt

比方说要对add merge此次提交打标签,它对应的commit id是6224937,敲入命令:
$ git tag v0.9 6224937

再用命令git tag查看标签:
$ git tag
v0.9
v1.0

注意,标签不是按时间顺序列出,而是按字母排序的。能够用git show <tagname>查看标签信息

还能够建立带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164

操做标签

若是标签打错了,也能够删除:
$ git tag -d v0.1

由于建立的标签都只存储在本地,不会自动推送到远程。因此,打错的标签能够在本地安全删除。

若是要推送某个标签到远程,使用命令git push origin <tagname>:
$ git push origin v1.0

或者,一次性推送所有还没有推送到远程的本地标签:
$ git push origin --tags

能够删除一个远程标签
$ git push origin :refs/tags/tagname

相关文章
相关标签/搜索