本篇文章將對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鏈接,方便推送不用輸入郵箱密碼,請參考下面連接:
這是個人第一篇萬字博客!但願你們可以喜歡並從中收穫到知識 若是你以爲本篇文章對你有幫助,不妨關注我並點擊右下角的點贊和收藏!! 大家的支持就是我最大的動力~~