最近看了廖雪峯老師的git教程,通俗易懂,操做性很強,是很好的入門教程,javascript
網站連接:https://www.liaoxuefeng.com/,現記錄下學習筆記java
在Windows上使用Git,能夠從Git官網直接(https://git-scm.com/downloads),而後按默認選項安裝便可。安裝完成後,在開始菜單裏找到「Git」->「Git Bash」,蹦出一個相似命令行窗口的東西,就說明Git安裝成功!git
git-bash默認不能複製黏貼須要設置github
使用的時候ctrl+c ,在git-bash中右鍵就能夠複製安全
注意git-bash使用的命令與用cmd打開控制檯命令有區別,切換e盤git-bash使用的命令是cd e: cmd打開控制檯使用的命令是e:bash
安裝完成後,還須要最後一步設置,在命令行輸入:app
$ git config --global user.name "Your Name" $ git config --global user.email "email@example.com"
(1)在合適的地方新建一個文件夾learngit,cd 進入這個文件夾,pwd後會顯示這個文件夾的目錄ssh
(2)經過命令$ git init把這個目錄變成Git能夠管理的倉庫,這時learngit文件夾中多了一個.git目錄,這個目錄是Git來跟蹤管理版本庫的,不要改動,若是你沒有看到.git
目錄,那是由於這個目錄默認是隱藏的,用ls -ah
命令就能夠看見。編輯器
(3)用notepade++或者其它編輯器(不要用記事本) 新建一個文件readme.txt,並輸入內容,放到learngit文件夾裏學習
(4)用命令$ git add readme.txt告訴Git,把文件添加到倉庫
(5)用命令$ git commit -m "wrote a readme file"告訴Git,把文件提交到倉庫
爲何Git添加文件須要add
,commit
一共兩步呢?由於commit
能夠一次提交不少文件,因此你能夠屢次add
不一樣的文件,好比:
$ git add file1.txt $ git add file2.txt file3.txt $ git commit -m "add 3 files."
咱們已經成功地添加並提交了一個readme.txt文件,如今,是時候繼續工做了,因而,咱們繼續修改readme.txt文件,修改後運行$ git status命令看看結果:
雖然Git告訴咱們readme.txt被修改了,但若是能看看具體修改了什麼內容,天然是很好的,經過命令查看修改 $ git diff readme.txt ,修改後跟上面是同樣的經過$ git add readme.tx,$ git commit -m "wrote a readme file" 提交修改
提交後,咱們再用git status
命令看看倉庫的當前狀態:
$ git status
若提交了多個版本,咱們須要回退到指定的版本,首先咱們查看總共有多少個版本,經過命令 $ git log ,$ git log顯示的信息比較全,比較眼花繚亂,可使用 命令$ git log --pretty=oneline 顯示簡短信息
首先,Git必須知道當前版本是哪一個版本,在Git中,用HEAD
表示當前版本,也就是最新的提交,上一個版本就是HEAD^
,上上一個版本就是HEAD^^
,若是往上多的話寫成HEAD~數字
。
$ git reset --hard HEAD^ //回到上一個版本
這時最新的那個版本經過命令 $ git log 查看已經不存在了,若是須要穿梭回來須要找到commit id
git reflog
用來記錄你的每一次命令:$ git reflog
learngit
文件夾就是一個工做區:工做區有一個隱藏目錄.git,這個不算工做區,而是Git的版本庫。
Git的版本庫裏存了不少東西,其中最重要的就是稱爲stage(或者叫index)的暫存區,還有Git爲咱們自動建立的第一個分支master,以及指向master的一個指針叫HEAD。
前面講了咱們把文件往Git版本庫裏添加的時候,是分兩步執行的:
第一步是用git add把文件添加進去,實際上就是把文件修改添加到暫存區;
第二步是用git commit提交更改,實際上就是把暫存區的全部內容提交到當前分支。
每次修改,若是不add到暫存區,那就不會加入到commit中。
一、未add到暫存區,只在工做區 $ git checkout -- readme.txt
2 、git add到暫存區了:慶幸的是,在commit以前,Git一樣告訴咱們,用命令git reset HEAD file能夠把暫存區的修改撤銷掉(unstage),從新放回工做區:
git reset HEAD readme.txt
git checkout -- readme.txt 丟棄工做區的修改
三、如今,假設你不但改錯了東西,還從暫存區提交到了版本庫,怎麼辦呢?還記得版本回退一節嗎?能夠回退到上一個版本。刪除並提交後能夠經過 $ git reset --hard HEAD^回退到刪除前
通常狀況下,你一般直接在文件管理器中把沒用的文件刪了,或者用rm
命令刪了:
$ rm test.txt
如今你有兩個選擇,一是確實要從版本庫中刪除該文件,那就用命令git rm
刪掉,而且git commit
:
$ git rm test.txt $ git commit -m "remove test.txt"
如今,文件就從版本庫中被刪除了。
另外一種狀況是刪錯了,由於版本庫裏還有呢,因此能夠很輕鬆地把誤刪的文件恢復到最新版本:
$ git checkout -- test.txt
自行註冊GitHub帳號。因爲你的本地Git倉庫和GitHub倉庫之間的傳輸是經過SSH加密的,因此,須要一點設置,建立SSH Key ,cd 切換到learngit,經過命令
$ ssh-keygen -t rsa -C "youremail@example.com"
使用默認值不停的回車確認,會在C:\Users\Administrator文件夾裏生成.ssh目錄,裏面有id_rsa
和id_rsa.pub
兩個文件,這兩個就是SSH Key的祕鑰對,id_rsa
是私鑰,不能泄露出去,id_rsa.pub
是公鑰,能夠放心地告訴任何人。而後打開GitHub網站,進入setting-SSH and GPG keys頁面,點「Add SSH Key」,填上任意Title,在Key文本框裏粘貼id_rsa.pub
文件的內容,就有了本身的遠程倉庫。
如今的情景是,你已經在本地建立了一個Git倉庫後,又想在GitHub建立一個Git倉庫,而且讓這兩個倉庫進行遠程同步,這樣,GitHub上的倉庫既能夠做爲備份,又可讓其餘人經過該倉庫來協做,真是一舉多得。
一、登陸GitHub,在右上角的+裏面有個New repository,在Repository name填入learngit
,其餘保持默認設置,點擊「Create repository」按鈕,就成功地建立了一個新的Git倉庫:
二、在本地的learngit
倉庫下運行命令:
$ git remote add origin git@github.com:tianyawhl123/learngit.git
添加後,遠程庫的名字就是origin
,這是Git默認的叫法,也能夠改爲別的,可是origin
這個名字一看就知道是遠程庫。
三、就能夠把本地庫的全部內容推送到遠程庫上:
$ git push -u origin master
把本地庫的內容推送到遠程,用git push
命令,其實是把當前分支master
推送到遠程。
因爲遠程庫是空的,咱們第一次推送master
分支時,加上了-u
參數,Git不但會把本地的master
分支內容推送的遠程新的master
分支,還會把本地的master
分支和遠程的master
分支關聯起來,在之後的推送或者拉取時就能夠簡化命令。
從如今起,只要本地做了提交,就能夠經過命令:
$ git push origin master
在建立遠程庫的時候勾選Initialize this repository with a README
,這樣GitHub會自動爲咱們建立一個README.md
文件。建立完畢後,能夠看到README.md
文件:
如今,遠程庫已經準備好了,下一步是用命令git clone
克隆一個本地庫:
$ git clone git@github.com:michaelliao/gitskills.git
首先,咱們建立dev
分支,而後切換到dev
分支:
$ git checkout -b dev
git checkout
命令加上-b
參數表示建立並切換,至關於如下兩條命令:
$ git branch dev $ git checkout dev
而後,用git branch
命令查看當前分支:
$ git branch
而後提交:
$ git add readme.txt $ git commit -m "branch test"
如今,dev
分支的工做完成,咱們就能夠切換回master
分支:
$ git checkout master
如今,咱們把dev
分支的工做成果合併到master
分支上:
$ git merge dev
合併完成後,就能夠放心地刪除dev
分支了:
$ git branch -d dev
新建分支並指向此分支
$ git checkout -b feature1
修改readme.txt最後一行內容並在feature1分支上add和commit
切換到master
分支:
$ git checkout master
也修改readme.txt的最後一行,並在master分支上add和commit
如今master分支和feature1分支各自都分別有新的提交
此時在master分支上合併feature1會出現衝突
$ git merge feature1
Git用<<<<<<<
,=======
,>>>>>>>
標記出不一樣分支的內容,咱們修改後後保存,再add和commit提交
用帶參數的git log
也能夠看到分支的合併狀況:
$ git log --graph --pretty=oneline --abbrev-commit
最後刪除feature1分支
$ git branch -d feature1
在實際開發中,咱們應該按照幾個基本原則進行分支管理:
首先,master
分支應該是很是穩定的,也就是僅用來發布新版本,平時不能在上面幹活;
那在哪幹活呢?幹活都在dev
分支上,也就是說,dev
分支是不穩定的,到某個時候,好比1.0版本發佈時,再把dev
分支合併到master
上,在master
分支發佈1.0版本;
你和你的小夥伴們每一個人都在dev
分支上幹活,每一個人都有本身的分支,時不時地往dev
分支上合併就能夠了。
一般,合併分支時,若是可能,Git會用Fast forward
模式,但這種模式下,刪除分支後,會丟掉分支信息。
若是要強制禁用Fast forward
模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就能夠看出分支信息。
合併dev
分支,請注意--no-ff
參數,表示禁用Fast forward
:
$ git merge --no-ff -m "merge with no-ff" dev
軟件開發中,bug就像屢見不鮮同樣。有了bug就須要修復,在Git中,因爲分支是如此的強大,因此,每一個bug均可以經過一個新的臨時分支來修復,修復後,
合併分支,而後將臨時分支刪除。
當你接到一個修復一個代號101的bug的任務時,很天然地,你想建立一個分支issue-101來修復它,可是,等等,當前正在dev上進行的工做尚未提交:
並非你不想提交,而是工做只進行到一半,還無法提交,預計完成還需1天時間。可是,必須在兩個小時內修復該bug,怎麼辦?
幸虧,Git還提供了一個stash功能,能夠把當前工做現場「儲藏」起來,等之後恢復現場後繼續工做:
$ git stash,如今,用git status查看工做區,就是乾淨的(除非有沒有被Git管理的文件),所以能夠放心地建立分支來修復bug。
首先肯定要在哪一個分支上修復bug,假定須要在master分支上修復,就從master建立臨時分支:
$ git checkout master
$ git checkout -b issue-101
如今修復bug,須要把「Git is free software ...」改成「Git is a free software ...」,而後提交:
$ git add readme.txt
$ git commit -m "fix bug 101"
修復完成後,切換到master分支,並完成合並,最後刪除issue-101分支:
$ git checkout master
$ git merge --no-ff -m "merged bug fix 101" issue-101
$ git branch -d issue-101
是時候接着回到dev分支幹活了!
$ git checkout dev
工做區是乾淨的,剛纔的工做現場存到哪去了?用git stash list命令看看:
$ git stash list
工做現場還在,Git把stash內容存在某個地方了,可是須要恢復一下,有兩個辦法:
一是用git stash apply恢復,可是恢復後,stash內容並不刪除,你須要用git stash drop來刪除;
另外一種方式是用git stash pop,恢復的同時把stash內容也刪了:
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,而且,遠程倉庫的默認名稱是origin。
要查看遠程庫的信息,用git remote:
或者,用git remote -v顯示更詳細的信息:
$ git remote -v
origin git@github.com:michaelliao/learngit.git (fetch)
origin git@github.com:michaelliao/learngit.git (push)
上面顯示了能夠抓取和推送的origin的地址。若是沒有推送權限,就看不到push的地址。
推送分支
推送分支,就是把該分支上的全部本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上:$ git push origin master
若是要推送其餘分支,好比dev,就改爲:$ git push origin dev
可是,並非必定要把本地分支往遠程推送,那麼,哪些分支須要推送,哪些不須要呢?
master分支是主分支,所以要時刻與遠程同步;
dev分支是開發分支,團隊全部成員都須要在上面工做,因此也須要與遠程同步;
bug分支只用於在本地修復bug,就不必推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
feature分支是否推到遠程,取決於你是否和你的小夥伴合做在上面開發。
抓取分支
多人協做時,你們都會往master和dev分支上推送各自的修改。
如今,模擬一個你的小夥伴,能夠在另外一臺電腦(注意要把SSH Key添加到GitHub)或者同一臺電腦的另外一個目錄下克隆:
$ git clone git@github.com:michaelliao/learngit.git
當你的小夥伴從遠程庫clone時,默認狀況下,你的小夥伴只能看到本地的master分支。不信能夠用git branch命令看看:
$ git branch
* master
如今,你的小夥伴要在dev分支上開發,就必須建立遠程origin的dev分支到本地,因而他用這個命令建立本地dev分支:$ git checkout -b dev origin/dev
如今,他就能夠在dev上繼續修改,而後,時不時地把dev分支push到遠程:
$ git add readme.txt $ git commit -m "add /usr/bin/env"
$ git push origin dev
你的小夥伴已經向origin/dev分支推送了他的提交,而碰巧你也對一樣的文件做了修改,並試圖推送:
$ git add hello.py
$ git commit -m "add coding: utf-8"
$ git push origin dev
推送失敗,由於你的小夥伴的最新提交和你試圖推送的提交有衝突,解決辦法也很簡單,Git已經提示咱們,先用git pull把最新的提交從origin/dev抓下來,而後,在本地合併,解決衝突,再推送:
$ git pull
git pull也失敗了,緣由是沒有指定本地dev分支與遠程origin/dev分支的連接,根據提示,設置dev和origin/dev的連接:
$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
再pull:
$ git pull
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.
這回git pull成功,可是合併有衝突,須要手動解決,解決的方法和分支管理中的解決衝突徹底同樣。解決後,提交,再push:
$ git add hello.py $ git commit -m "merge & fix hello.py"
$ git push origin dev
所以,多人協做的工做模式一般是這樣:
首先,能夠試圖用git push origin branch-name推送本身的修改;
若是推送失敗,則由於遠程分支比你的本地更新,須要先用git pull試圖合併;
若是合併有衝突,則解決衝突,並在本地提交;
沒有衝突或者解決掉衝突後,再用git push origin branch-name推送就能成功!
若是git pull提示「no tracking information」,則說明本地分支和遠程分支的連接關係沒有建立,用命令git branch --set-upstream branch-name origin/branch-name。
這就是多人協做的工做模式,一旦熟悉了,就很是簡單。
在Git中打標籤很是簡單,首先,切換到須要打標籤的分支上:
$ git branch
$ git checkout master
而後,敲命令git tag <name>就能夠打一個新標籤:$ git tag v1.0
能夠用命令git tag查看全部標籤:$ git tag
默認標籤是打在最新提交的commit上的。有時候,若是忘了打標籤,好比,如今已是週五了,但應該在週一打的標籤沒有打,怎麼辦?
方法是找到歷史提交的commit id,而後打上就能夠了:
$ git log --pretty=oneline --abbrev-commit
比方說要對add merge此次提交打標籤,它對應的commit id是6224937,敲入命令:
$ git tag v0.9 6224937
再用命令git tag查看標籤:
$ git tag
v0.9
v1.0
注意,標籤不是按時間順序列出,而是按字母排序的。能夠用git show <tagname>查看標籤信息:
$ git show v0.9
還能夠建立帶有說明的標籤,用-a指定標籤名,-m指定說明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164
小結
命令git tag <name>用於新建一個標籤,默認爲HEAD,也能夠指定一個commit id;
git tag -a <tagname> -m "blablabla..."能夠指定標籤信息;
git tag -s <tagname> -m "blablabla..."能夠用PGP簽名標籤;
命令git tag能夠查看全部標籤。
操做標籤
若是標籤打錯了,也能夠刪除:$ git tag -d v0.1
由於建立的標籤都只存儲在本地,不會自動推送到遠程。因此,打錯的標籤能夠在本地安全刪除。
若是要推送某個標籤到遠程,使用命令git push origin <tagname>:$ git push origin v1.0
或者,一次性推送所有還沒有推送到遠程的本地標籤:
$ git push origin --tags
若是標籤已經推送到遠程,要刪除遠程標籤就麻煩一點,先從本地刪除:
$ git tag -d v0.9
而後,從遠程刪除。刪除命令也是push,可是格式以下:
$ git push origin :refs/tags/v0.9
要看看是否真的從遠程庫刪除了標籤,能夠登錄GitHub查看。
標籤管理小結
命令git push origin <tagname>能夠推送一個本地標籤;
命令git push origin --tags能夠推送所有未推送過的本地標籤;
命令git tag -d <tagname>能夠刪除一個本地標籤;
命令git push origin :refs/tags/<tagname>能夠刪除一個遠程標籤。