本篇文章将对git在工做和学习中须要用到的大部分经常使用指令做详细解答,git
以为有用的C友们能够点个赞支持一下,大家的支持就是我最大的动力~github
本文总结自廖雪峰老师的文档
安全
1.git的初步认识markdown
4.版本回退git reset与查看日志git log/git relog分布式
5.撤销修改git checkout及git reset(再说起)oop
6.删除文件学习
7.分支管理 branch与switchfetch
首先,Git在本地中具备工做区、暂存区与本地仓库区 平时咱们修改代码时叫作工做区,当你完成项目到某个进度想保存时,那么即可将代码存到暂存区,暂存区相似于word文件中的自动保存功能,当你确认暂存区中的代码没问题要保存时,即可将代码由暂存区转到本地仓库区。
那么对于一个目录,如何将它变成Git能够管理的仓库呢?(本地仓库,还不是远程仓库) 答案是:在当前目录下运行git init
指令建立一个版本库,而后这个目录里面的全部文件就能够被Git管理起来,每一个文件的修改、删除,Git都能跟踪,以便任什么时候刻均可以追踪历史,或者在未来某个时刻能够“还原”。 能够发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,否则改乱了,就把Git仓库给破坏了,若是你没有看到.git目录,那是由于这个目录默认是隐藏的。
因为Github使用面更广,后续演示都是针对Github来展开
整体来讲,把一个文件放到本地Git仓库只须要两步。
git add
告诉Git,把某个文件从工做区添加到暂存区。git add <file>
$ git add readme.txt//将readme.txt文件添加到暂存区
复制代码
执行上面的命令,若是没有任何显示,表明正确运行。
git commit
告诉Git,将暂存区中全部文件一次性从暂存区添加到本地仓库区。git commit -m <message>
$ git commit -m "wrote a readme file"//将readme.txt文件添加到本地仓库
复制代码
:boom:详解:boom: . 简单解释一下git commit命令,-m后面输入的是本次提交的说明,能够输入任意内容,固然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。git commit命令执行成功后会告诉你,1 file changed:1个文件被改动(咱们新添加的readme.txt文件);2 insertions:插入了两行内容(readme.txt有两行内容)。
为何Git添加文件须要add
,commit
一共两步呢?由于commit
能够一次提交不少文件,因此你能够屡次add
不一样的文件,好比:
$ git add file1.txt
$ git add file2.txt file3.txt//一次add命令能够有多个文件,用空格分隔
$ git commit -m "add 3 files."
复制代码
git status
命令能查看当前目录中全部文件的代码状态,若是文件是红色那说明文件被修改过但还没将这次修改提交。 git diff
命令顾名思义就是查看difference,显示的格式正是Unix通用的diff格式,git diff
后面跟文件名称是是查看工做区(working tree)与暂存区(index)的差异的
你不断对文件进行修改,而后不断提交修改到版本库里,就比如玩游戏时,每经过一关就会自动把游戏状态存盘,若是某一关没过去,你还能够选择读取前一关的状态。有些时候,在打Boss以前,你会手动存盘,以便万一打Boss失败了,能够从最近的地方从新开始。Git也是同样,每当你以为文件修改到必定程度的时候,就能够“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还能够从最近的一个commit恢复,而后继续工做,而不是把几个月的工做成果所有丢失,这就是版本回退。
假设对于readme.txt文件,我已经提交了三个版本的修改,而对于git commit -m <message>
,-m后面输入的本次提交说明以下:
版本1:wrote a readme file 版本2:add distributed 版本3:append GPL(最新版本)
固然,在实际工做中,咱们脑子里怎么可能记得一个几千行的文件每次都改了什么内容,否则要版本控制系统Git干什么。版本控制系统确定有某个命令能够告诉咱们历史记录,在Git中,咱们用git log
命令查看:
$ git log
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)//最新的一次修改
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800
append GPL
commit e475afc93c209a690c39c13a46716e8fa000c366
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:03:36 2018 +0800
add distributed
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 20:59:18 2018 +0800
wrote a readme file
复制代码
若是嫌输出信息太多,看得眼花缭乱的,能够试试加上--pretty=oneline
参数
$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL//最新的一次修改
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file
复制代码
:boom:友情提示:你看到的一大串相似1094adb...的是commit id(版本号),你看到的commit id和个人确定不同,以你本身的为准。为何commit id须要用这么一大串数字表示呢?由于Git是分布式的版本控制系统,后面咱们还要研究多人在同一个版本库里工做,若是你们都用1,2,3……做为版本号,那确定就冲突了。版本号不必写全,前几位就能够了,Git会自动去找
打算把readme.txt回退到上一个版本,也就是add distributed的那个版本,怎么作呢? 首先,Git必须知道当前版本是哪一个版本,在Git中,用HEAD表示当前版本,也就是最新的提交1094adb...(注意个人提交ID和你的确定不同),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,固然往上100个版本写100个^比较容易数不过来,因此写成HEAD~100
。
如今,咱们要把当前版本append GPL回退到上一个版本add distributed,就可使用git reset
$ git reset --hard HEAD^//去上一个版本
HEAD is now at e475afc add distributed
复制代码
也能够指定某个commit版本进行还原
$ git reset --hard 1094a//指定commit版本前五位数为1094a的进行还原
HEAD is now at 83b0afe append GPL
复制代码
若是你忘记了commit版本号,能够经过git reflog
来找,git reflog
记录了你的每一次命令
$ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file
复制代码
:boom:过程图示: 总结:
HEAD
指向的版本就是当前版本,所以,Git容许咱们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。
git log
能够查看提交历史,以便肯定要回退到哪一个版本。git reflog
查看命令历史,以便肯定要回到将来的哪一个版本。当你对工做区文件完成修改时,你能够选择git add
提交到暂存区,也能够选择git checkout
撤销这次修改
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
复制代码
命令git checkout -- readme.txt
意思就是,把readme.txt
文件在工做区的修改所有撤销, 这里有两种状况: 一种是readme.txt
自修改后尚未被放到暂存区,如今,撤销修改就回到和版本库如出一辙的状态; 一种是readme.txt
已经添加到暂存区后,又做了修改,如今,撤销修改就回到上次提交到暂存区后的状态。 总之,就是让这个文件回到最近一次git commit
或git add
时的状态。
当你对工做区文件完成修改且已经提交到了暂存区,你能够选择git commit
提交到本地仓库区,也能够选择git reset
把暂存区的修改撤销掉
$ git reset HEAD readme.txt//前文讲过,HEAD表明当前最新版本的文件
Unstaged changes after reset:
M readme.txt
复制代码
git reset
命令既能够回退版本,也能够把暂存区的修改撤销到工做区。何时须要撤销本地仓库区的修改呢?那即是已经git commit
到本地仓库了,那便回到前文的版本回退章节进行查阅,git reset --hard 指定版本
便可
在Git中,删除也是一个修改操做 通常状况下,你一般直接在文件管理器中把没用的文件删了,或者用rm <file>
命令删了
$ rm test.txt
复制代码
这个时候,Git知道你删除了文件,所以,工做区和版本库就不一致了
git checkout
指令恢复(撤销本次修改)$ git checkout -- test.txt
复制代码
git rm
删掉,再git commit
提交本次修改$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
复制代码
小提示:先手动删除文件,而后使用git rm 和git add效果是同样的。
分支在实际中有什么用呢?假设你准备开发一个新功能,可是须要两周才能完成,第一周你写了50%的代码,若是马上提交,因为代码还没写完,不完整的代码库会致使别人不能干活了。若是等代码所有写完再一次提交,又存在丢失天天进度的巨大风险。 如今有了分支,就不用怕了。你建立了一个属于你本身的分支,别人看不到,还继续在原来的分支上正常工做,而你在本身的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工做。
:boom:用branch
系列指令进行分支相关操做
用git branch
命令列出本地仓库中全部分支,当前分支前面会标一个*
号
$ git branch
* dev
master
复制代码
git branch dev
建立dev分支 git checkout dev
将HEAD指针切换到dev分支
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
复制代码
git checkout -b dev
git checkout命令加上-b参数表示建立并切换,至关于上面两条命令 先建立dev分支,而后切换到dev分支
$ git checkout -b dev
Switched to a new branch 'dev'
复制代码
当你在dev
分支上对readme.txt
文件进行修改后,想将该修改合并到master
主分支上时,两步:
先git checkout 分支名
切换到master
分支
$ git checkout master
Switched to branch 'master'
复制代码
再git merge 须要被合并的分支名
合并dev分支
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
复制代码
合并完成后,就能够删除dev分支了,相较于git checkout dev
添加分支,加个参数-d
表明delete
$ git branch -d dev
Deleted branch dev (was b17d20e).
复制代码
:boom:用switch
系列指令进行分支相关操做
注意到切换分支使用git checkout <branch>
,而前面讲过的撤销修改则是git checkout -- <file>
,同一个命令,有两种做用,确实有点使人迷惑。
实际上,切换分支这个动做,用switch
更容易理解。所以,最新版本的Git提供了新的git switch
命令来切换分支:
建立并切换到新的dev
分支,可使用:
$ git switch -c dev//代替git checkout -b dev
复制代码
直接切换到已有的master
分支,可使用:
$ git switch master//代替git branch dev
复制代码
:boom:总结:
查看分支:git branch
建立分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
建立+切换分支:git checkout -b <name>
或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
前言:为何要使用标签?
发布一个版本时,咱们一般先在版本库中打一个标签(tag),这样,就惟一肯定了打标签时刻的版本。未来不管何时,取某个标签的commit版本,就是把那个打标签的时刻的历史版本取出来。因此,标签也是版本库的一个快照。 Git有commit版本号,为何还要引入tag? 由于commit版本是相似6a5819e...
的一大串字符,很差找、辨别 若是将6a5819e...
变成v1.2
,就容易了不少 因此,tag就是一个让人容易记住的有意义的名字,它跟某个commit版本号绑在一块儿。
git tag <tagname>
git tag -a <tagname> -m "blablabla..."
首先,git branch
切换到须要打标签的分支上
$ git branch
* dev
master
$ git checkout master
Switched to branch 'master'
复制代码
而后git tag <tagname>
打标签便可
$ git tag v1.0
复制代码
git tag <tagname> <commid id>
默认标签是打在最新提交的commit上的,历史的找到历史提交的commit id,而后打上就能够了
比方说要对add merge
此次提交打标签,它对应的commit id是f52c633
$ git tag v0.9 f52c633
复制代码
还能够建立带有说明的标签,用-a指定标签名,-m指定说明文字 git tag -a <tagname> -m "blablabla..." <commit id>
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
复制代码
git tag
能够用命令git tag查看全部标签
$ git tag
v1.0
复制代码
git show <tagname>
标签不是按时间顺序列出,而是按字母排序的。能够用git show <tagname>
查看标签信息:
$ git show v0.9
commit f52c63349bc3c1593499807e5c8e972b82c8f286 (tag: v0.9)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:56:54 2018 +0800
add merge
diff --git a/readme.txt b/readme.txt
...
复制代码
命令git tag -d <tagname>
能够删除一个本地标签;
命令git push origin :refs/tags/<tagname>
能够删除一个远程标签。
命令git push origin <tagname>
能够推送一个本地标签;
命令git push origin --tags
能够推送所有未推送过的本地标签;
目前广为人知的两个远程仓库有Github和Gitee(码云)
Github:人气最高,人们广泛使用的一个国际化代码管理平台
Gitee:使用GitHub时,国内的用户常常遇到的问题是访问速度太慢,有时候还会出现没法链接的状况 若是咱们但愿体验Git飞通常的速度,可使用国内的Git托管服务——Gitee(gitee.com)
目标: 在本地建立了一个Git仓库后,又想在GitHub建立一个Git仓库,而且让这两个仓库进行远程同步。
git remote add 远程仓库名字 git@github.com:远程仓库路径//远程仓库路径以下图
$ git remote add origin git@github.com:michaelliao/learngit.git
复制代码
创建好链接后,远程库的名字就是origin,这是Git默认的叫法,也能够改为别的,可是origin这个名字一看就知道是远程库。
git push -u 远程仓库名称 要推送的本地分支名称
$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.64 KiB | 560.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
To github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
复制代码
把本地库的内容推送到远程,用git push
命令,其实是把当前分支master
推送到远程。
因为远程库是空的,咱们第一次推送master分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在之后的推送或者拉取时就能够简化命令。
从如今起,只要本地做了提交,就能够经过命令:
$ git push origin master//origin依旧为远程库名称,master为要推送的分支名称
复制代码
在删除前,建议先用git remote -v
查看远程库信息
$ git remote -v
origin git@github.com:michaelliao/learn-git.git (fetch)
origin git@github.com:michaelliao/learn-git.git (push)
复制代码
git remote rm <name>
删除远程库,name为远程库名称 好比删除前文建立的名为origin的远程库
$ git remote rm origin
复制代码
舒适提示:此处的“删除”实际上是解除了本地和远程的绑定关系,并非物理上删除了远程库。远程库自己并无任何改动。要真正删除远程库,须要登陆到GitHub,在后台页面找到删除按钮再删除。
:boom:总结:
要关联一个远程库,使用命令git remote add 远程仓库名字 git@github.com:远程仓库路径
关联一个远程库时必须给远程库指定一个名字,origin是默认习惯命名;
关联后,使用命令git push -u 远程仓库名称 要推送的本地分支名称
第一次推送master分支的全部内容;
此后,每次本地提交后,只要有必要,就可使用命令git push -u 远程仓库名称 要推送的本地分支名称
推送最新修改;
你的本地Git仓库和GitHub仓库之间的传输方式有两种,一种是经过https,另外一种是经过SSH加密的
HTTPS:使用https url克隆对初学者来讲会比较方便,复制https url而后到git Bash里面直接用clone命令克隆到本地就行了,可是每次fetch和push代码都须要输入帐号和密码,这也是https方式的麻烦之处(发现了https免密登陆的方式)。
SSH:使用SSH url克隆却须要在克隆以前先配置和添加好SSH key,所以,若是你想要使用SSH url克隆的话,你必须是这个项目的拥有者或管理员,不然你是没法添加SSH key的。另外ssh默认是每次fetch和push代码都不须要输入帐号和密码
至于如何将本机与Github和Gitee创建SSH链接,方便推送不用输入邮箱密码,请参考下面连接:
这是个人第一篇万字博客!但愿你们可以喜欢并从中收获到知识 若是你以为本篇文章对你有帮助,不妨关注我并点击右下角的点赞和收藏!! 大家的支持就是我最大的动力~~