GIT基礎學習總結

學習完廖雪峯老師的git課堂,結合教學內容總結一下。linux

Git簡介

Git是分佈式版本控制系統。git

集中式vs分佈式github

1.集中式shell

典型:CVS,SVNbootstrap

解析:版本庫是集中存放在中央服務器的,中央服務器就比如是一個圖書館,你要改一本書,必須先從圖書館借出來,而後回到家本身改,改完了,再放回圖書館。安全

2.分佈式bash

分佈式版本控制系統根本沒有「中央服務器」,每一個人的電腦上都是一個完整的版本庫。但其實,有一臺充當「中央服務器」的電腦,但這個服務器的做用僅僅是用來方便「交換」你們的修改,沒有它你們也同樣幹活,只是交換修改不方便而已。服務器

Git的安裝

查看git是否安裝app

$git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git框架

1.Debian或Ubuntu Linux像如上提示安裝

2.老版本Debian或Ubuntu Linux :sudo apt-get install git-core

3.其餘linux發行版,用源碼安裝

(1).Git官網下載源碼,而後解壓

(2).依次執行

./config,make,sudo make install

Git的使用

1.初始化一個Git倉庫

倉庫,也叫版本庫,英文名repository,你能夠簡單理解成一個目錄。

1.建立一個空目錄

$mkdir learngit
$cd learngit
$pwd
/Users/michael/learngit

2.經過git init命令把這個目錄變成Git能夠管理的倉庫

$git init
Initialized empty Gitrepositoryin /Users/michael/learngit/.git/

2.文件管理

1.將文件添加到Git倉庫

以readme.txt爲例。注意這個文件必定要在git倉庫下,即目錄learngit或其子目錄下。

1.用命令git add告訴Git,把文件添加到倉庫

$git add readme.txt
2.用命令git commit告訴Git,把文件添加到倉庫

$ git commit -m "wrote a readme file"

[master (root-commit) cb926e7] wrote a readme file

1file changed,2insertions(+)

create mode 100644 readme.txt

2.查看倉庫狀態 & 提交修改

將文件添加到版本庫後,用命令git status查看倉庫狀態。

$git status

On branch master

nothing to commit (working directory clean)

git告訴咱們工做目錄是乾淨(working directory clean)!

修改readme.txt文件後,用命令git status查看倉庫狀態。

$git status

On branch master

Changes not staged for commit:

(use "git add ..." to update what will be committed)

(use "git checkout -- ..." to discard changes in working directory)

modified:  readme.txt

no changes added to commit (use"git add"and/or"git commit -a")
上面的命令告訴咱們,readme.txt被修改過了,但尚未準備提交的修改。

查看修改:

$ git diff readme.txt

如上命令會提示修改詳細。

提交修改:

  • 第一步:git add *

$git add readme.txt

在進行第二步git commit前,查看一下倉庫狀態

$ git status

On branch master

Changes to be committed:

(use "git reset HEAD..." to unstage)



  modified:  readme.txt

git告訴咱們,將要被提交的修改包括readme.txt,下一步:放心提交

  • 第二步:git commit *

$ git commit -m "add distributed"

[master ea34578]add distributed

1 file changed,1 insertion(+),1 deletion(-)

提交後,再次查看倉庫狀態

$ git status

On branch master

nothing to commit (working directory clean)

Git告訴咱們工做目錄是乾淨(working directory clean)的,沒有要提交的修改。

3.版本回退

Git容許咱們在版本的歷史之間穿梭,使用命令 git reset --hard commit_id

1.HEAD指向當前版本,上一個版本就是HEAD^,上上一個版本就是HEAD^^

2.回到上個版本:git reset --hard HEAD^ , 回到上上個版本:git reset --hard HEAD^^

3.回到歷史某個版本:首先用git log 查看提交歷史,而後利用commit id使用命令如:git reset --hard 3628164 (版本號不必寫全,前幾位就能夠了,Git會自動去找)

4.從歷史某個版本回到如今:首先用git reflog查看命令歷史,以便肯定要回到將來的哪一個版本。

$ git reflog

ea34578 HEAD@{0}: reset: moving to HEAD^

3628164 HEAD@{1}: commit: append GPL

ea34578 HEAD@{2}: commit: add distributed

cb926e7 HEAD@{3}: commit (initial): wrote a readme file

回到append GPL版本即: git reset --hard 3628164

4.工做區,暫存區和版本庫

1.工做區(Working Directory)

就是你在電腦裏能看到的目錄,好比個人learngit文件夾就是一個工做區。

2.版本庫(Repository)

工做區有一個隱藏目錄.git,這個不算工做區,而是Git的版本庫。

3.暫存區(stage/index)

Git的版本庫裏存了不少東西,其中最重要的就是成爲stage或者index的暫存區。還有Git爲咱們自動建立的master分支,以及指向master的指針叫HEAD。

clipboard.png

回憶一下,把文件添加到版本庫分兩步。

第一步:git add,添加文件。實際就是把文件添加到暫存區。

第二步:git commit,提交修改。實際就是把暫存區的內容提交到當前分支。

能夠簡單理解爲:第一步是將要提交的修改通通放到暫存區。第二步是一次性提交全部修改。

繼續實踐:

如今git庫有個文件readme.txt,而且工做空間乾淨了。

咱們修改文件readme.txt,再添加一個新文件test.txt。

而後查看工做空間狀態。

$ git status

On branch master

Changes not staged for commit:

(use "git add..." to update what will be committed)

(use "git checkout --..." to discard changes in working directory)

modified:  readme.txt

Untracked files:

(use "git add..." to include in what will be committed)

test.txt

no changes added to commit (use "git add" and/or "git commit -a")
Git很是清楚地告訴咱們,readme.txt被修改了,而test.txt還歷來沒有被添加過,因此它的狀態是Untracked。

把兩個文件添加到暫存區

$git add readme.txt

$git add test.txt

再次查看狀態

$ git status

On branch master
Changes to be committed:
(use "git reset HEAD..." to unstage)

new file:  LICENSE

  modified:  readme.txt

Git提示咱們有未提交的修改,咱們圖示一下暫存區狀態。

clipboard.png

經過圖示可清楚看到,經過git add命令將文件提交到了暫存區。

下面咱們提交文件到Git版本庫。

$git commit -m "understand how stage works"

[master 27c9860] understand how stage works

2 files changed, 675 insertions(+)

create mode 100644 LICENSE

查看狀態

$git status

On branch master

nothing to commit (working directory clean)

圖示狀態

clipboard.png

5.管理修改

GIt之因此優秀,是由於不同凡響的是,它管理的是修改,並不是文件。

提交修改:

①修改→git add添加修改→git commit提交修改

②第一次修改→git add添加修改→git commit提交修改→第二次修改→git add添加修改→git commit提交修改

③第一次修改→git add添加修改→第二次修改→git add添加修改→git commit一塊兒提交修改

若是②中第二次修改沒有git add添加而直接git commit提交,那麼git status查看狀態,就會以下提示

$git status

......

no changes added to commit (use"git add"and/or"git commit -a")

git diff HEAD -- readme.txt命令能夠查看工做區和版本庫裏面最新版本的區別。

6.撤銷修改

1.修改文件,還未git add

使用命令git checkout -- file丟棄工做區的修改

1.若是暫存區無未提交的修改,版本庫會覆蓋本地

2.若是暫存區有未提交的修改,暫存區會覆蓋本地

總之,就是讓這個文件回到最近一次git commit或git add時的狀態。

2.修改文件,已經git add

第一步:使用命令git reset HEAD file能夠把暫存區的修改撤銷掉(unstage),從新放回工做區。

$ git reset HEAD readme.txt

Unstaged changes after reset:

  1. readme.txt

第二步:丟棄工做區的修改

$git checkout -- readme.txt

查看一下狀態,工做空間乾淨了。

$ git status

On branch master

nothing to commit (working directory clean)

7.刪除文件

在Git中,刪除也是一個修改操做。

1.新建一個文件,並提交到版本庫

$ git add test.txt

$ git commit -m "add test.txt"

2.從版本庫刪除它

第一步:在工做空間中刪了,而後查看狀態,git告訴咱們工做區和版本庫不同了

$rm test.txt
$git status

On branch master

Changes not staged for commit:

(use "git add/rm..." to update what will be committed)

  (use "git checkout --..." to discard changes in working directory)



 deleted:    test.txt

no changes added to commit (use "git add" and/or "git commit -a")

第二步:從版本庫刪除該文件

$ git rm test.txt

rm 'test.txt'

$ git commit -m "remove test.txt"

[master d17efd8] remove test.txt

1 file changed, 1 deletion(-)

delete mode 100644 test.txt

另外一種狀況是,若是本地刪除了該文件,發現是誤刪,能夠用版本庫恢復本地誤刪的文件。

$git checkout -- test.txt

git checkout實際上是用版本庫裏的版本替換工做區的版本,不管工做區是修改仍是刪除,均可以「一鍵還原」。

8.遠程倉庫

設置

因爲你的本地Git倉庫和GitHub倉庫之間的傳輸是經過SSH加密的,因此,須要一點設置:

第1步:建立SSH Key。打開Shell(Windows下打開Git Bash)

$ ssh-keygen -t rsa -C "youremail@example.com"

而後用戶主目錄裏能夠找到.ssh目錄,裏面有id_rsa和id_rsa.pub兩個文件,這兩個就是SSH Key的祕鑰對,id_rsa是私鑰,id_rsa.pub是公鑰。

第2步:登錄GitHub,打開「Account settings」→「SSH Keys」頁面→「New SSH key」,填上任意Title,在Key文本框裏粘貼id_rsa.pub文件的內容。

總結:Git支持SSH協議,經過SSH Key,它就能識別出你推送的提交確實是你推送的,而不是別人冒充的。

8.1 添加遠程庫

(1) 登陸Github 點擊右上角+ 選擇"New repository",添入Repository name,點擊Create repository

clipboard.png

clipboard.png

(2)Git提示咱們如何新建本地倉庫,並與之關聯,或把本地已有倉庫與之關聯。

1.新建本地倉庫,並與之關聯

$ mkdir GitTest

$ cd GitTest

$ git init

Initialized empty Git repository in /home/linn/GitTest/.git/

$ echo "# GitTest">>README.md

$ git add README.md

$ git commit -m "first commit"

$ git remote add origin https://github.com/dancenn/Gi...

$ git push -u origin master

2.與既存本地倉庫關聯

$ git remote add origin https://github.com/dancenn/Gi...

$ git push -u origin master

8.2 從遠程庫克隆

(1) 登陸Github 點擊右上角+ 選擇"New repository",添入Repository name,點擊Create repository

勾選Initialize this repository with a README,這樣GitHub會自動爲咱們建立一個README.md文件。

(2)用命令git clone克隆一個本地庫,並查看

$ git clone https://github.com/dancenn/Gi...

Cloning into 'GitTestClone'...

remote: Counting objects: 3, done.

remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0

Unpacking objects: 100% (3/3), done.

$ cd GitTestClone

$ ll

total 4

-rw-rw-r--. 1 linn linn 14 Aug 23 23:38 README.md

8.3分支管理

8.3.1.建立與合併分支

一開始先有master分支的時候,分支是一條線。master指向最新的提交,HEAD指向master。以此確認當前分支以及當前分支的提交點。

每次提交,master分支都向前移動一步,因此master分支會愈來愈長。以下:

若是新建一個dev分支,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:

$ git checkout -b dev

Switched to a new branch'dev'

用git branch命令查看當前分支:

$ git branch

  • dev

    master

如今,對工做區的提交就是針對dev分支的了,好比新提交一次後,dev指針往前移動一步,而master指針不變:

好比對readme.txt作個修改,而後提交:

$ 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'

而後就能夠把dev合併到master上。Git直接把master指向dev當前的提交,就完成了合併:

$ git merge dev

Updating d17efd8..fec145a

Fast-forward

readme.txt | 1 +

1 file changed, 1 insertion(+)
注意到上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。

固然,也不是每次合併都能Fast-forward,咱們後面會講其餘方式的合併。

合併完甚至能夠刪除dev,就又只剩master分支了:

$ git branch -d dev

Deleted branch dev (was fec145a).

$ git branch

  • master

小結

Git鼓勵大量使用分支:

查看分支:git branch

建立分支:git branch

切換分支:git checkout

建立+切換分支:git checkout -b

合併某分支到當前分支:git merge

刪除分支:git branch -d

2.解決衝突

準備了新的feature1分支,並提交了一些修改。切換到master分支,提交了不一樣的修改。

如今,master分支和feature1分支各自都分別有新的提交,變成了這樣:

這種狀況下,Git沒法執行「快速合併」,只能試圖把各自的修改合併起來,但這種合併就可能會有衝突:

$ git merge feature1

Auto-merging readme.txt

CONFLICT (content): Merge conflict in readme.txt

Automatic merge failed; fix conflicts and then commit the result.

而後,查看衝突,手動解決衝突。再次提交。而後再git merge feature1。分支變成了下圖所示:

用帶參數的git log也能夠看到分支的合併狀況:

$ git log --graph --pretty=oneline --abbrev-commit

  • 59bc1cb conflict fixed

|\

| * 75a857c AND simple

  • | 400b400 & simple

|/

  • fec145a branch test

...

最後,刪除feature1分支:

$ git branch -d feature1

Deleted branch feature1 (was 75a857c).

工做完成。

小結

當Git沒法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成。

git log --graph命令能夠看到分支合併圖。

3.分支管理策略

合併分支:

1.快速合併:Fast forward模式,若是可能,Git就會用這種模式,但刪除分支後,會丟掉分支信息。

2.普通合併:禁用Fast forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就能夠看出分支信息。

好比咱們要把dev分支合併到master分支上。

$ git checkout master

Switched to branch'master'

$ git merge --no-ff -m "merge with no-ff" dev

Merge made by the 'recursive' strategy.

readme.txt | 1 +

1 file changed, 1 insertion(+)

用git log看看分支歷史:

$ git log --graph --pretty=oneline --abbrev-commit

  • 7825a50 merge with no-ff

|\

| * 6224937 add merge

|/

  • 59bc1cb conflict fixed

...

能夠看到,不使用Fast forward模式,merge後就像這樣:

小結:

1.master分支應該是穩定的,用來發布版本,不在上面開發

2.dev分支用來開發,須要發佈版本時,就合併到master

3.不是直接在dev分支幹活,不一樣開發團隊在dev上建立本身的臨時分支,開發完往dev上合併

4.合併方式,儘可能使用普通合併,即加參數--no-ff。能看到合併歷史,而fast forward看不到合併歷史。

8.3.4.bug分支

若是你正在dev上開發,忽然接到一個緊急bug修改的任務,這時候本地工做還沒完,怎麼辦?幸虧Git提供了git stash的功能,它能把當前工做現場「儲藏」起來。

(1).「儲藏」現場

$ git stash

Saved working directory and index state WIP on dev: 6224937 add merge

HEAD is now at 6224937 add merge

(2).修改bug

$ git checkout -b issue-101

$ git add readme.txt

$ git commit -m "fix bug 101"

$ git checkout master

$ git merge --no-ff -m "merged bug fix 101"issue-101

$ git branch -d issue-101

(3).恢復現場

(3.1)先查看

$ git stash list

stash@{0}: WIP on dev: 6224937 add merge
(3.2).1 方法一

$ git stash apply

$ git stash drop
(3.2).2 方法二

$ git stash pop
(3.2).3 屢次stash場合

先用git stash list查看,而後恢復指定的stash,用命令:

$ git stash list

$ git stash apply stash@{0}
(3.3)再次查看,就沒有儲藏內容了

$ git stash list

5.Feature分支

新加一個功能,最好新建一個feature分支。

假設接到了一個新任務:開發代號爲new01的新功能,因而

$ git checkout -b feature-new01

$ git add new01.py

$ git commit -m"add feature new01"
此時新功能開發完並提交,下一步合併。但是忽然接到命令該功能廢棄。因此須要刪除分支。

$ git branch -d feature-new01

error: The branch 'feature-new01' is not fully merged.

If you are sure you want to delete it, run 'git branch -D feature-new01'.
Git友情提醒,feature-new01分支尚未被合併,若是刪除,將丟失掉修改,若是要強行刪除,須要使用命令git branch -D feature-new01。

$ git branch -D feature-new01

Deleted branch feature-new01 (was756d4af).

8.4.標籤管理

簡述:咱們一般習慣在版本庫打一個標籤來標識某一時刻的版本。之後能夠經過標籤取歷史版本。標籤是指向某個commit的指針,很像分支,可是分支能移動,標籤不能移動。

舉個栗子:

「請把上週一的那個版本打包發佈,commit號是6a5819e...」

「一串亂七八糟的數字很差找!」

「我要找的commit id是打了tag 「v1.1」的那個版本」

「找到了:git show v1.1」

8.4.1.建立標籤

(1).切換到須要打標籤的分支上

$ git checkout master

Switched to branch 'master'

(2).建立標籤

$ git tag v1.0
默認標籤是打在最新提交的commit上的。若是想給歷史提交打標籤

(2.1).找到歷史提交的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
(2.2).給歷史提交建立標籤

$ git tag v0.9 6224937
git tag查看標籤:

$ git tag

v0.9

v1.0

8.4.2.刪除標籤

(1).刪除標籤

$ git tag -d v0.1

Deleted tag 'v0.1' (was e078af9)
建立的標籤都只存儲在本地,不會自動推送到遠程。因此,打錯的標籤能夠在本地安全刪除。

(2).推送標籤

$ git push origin v0.1

Total 0 (delta 0), reused 0 (delta 0)

To git@github.com:michaelliao/learngit.git

  • [new tag] v1.0 -> v1.0

(3).一次性推送所有還沒有推送到遠程的本地標籤:

$ git push origin --tags

Counting objects: 1, done.

Writing objects: 100% (1/1), 554 bytes, done.

Total 1 (delta 0), reused 0 (delta 0)

To git@github.com:michaelliao/learngit.git

  • [new tag] v0.2 -> v0.2

  • [new tag] v0.9 -> v0.9

(4).刪除遠程標籤

(4.1) 先從本地刪除

$ git tag -d v0.9

Deleted tag 'v0.9' (was 6224937)

(4.2)從遠程刪除

$ git push origin :refs/tags/v0.9

To git@github.com:michaelliao/learngit.git

  • [deleted] v0.9

能夠登錄git hub看看是否刪除成功。

8.5 使用Github

如何參與開源項目?

8.5.1.Fork開源倉庫

以人氣比較高的很是強大的CSS框架bootstrap項目爲例。

訪問它的項目主頁https://github.com/twbs/boots...,點「Fork」就在本身的帳號下克隆了一個bootstrap倉庫。

8.5.2.從本身的帳號下clone

git clone git@github.com:april/bootstrap.git
必定要從本身的帳號下clone倉庫,這樣你纔有權限推送修改。

Bootstrap的官方倉庫twbs/bootstrap、你在GitHub上克隆的倉庫my/bootstrap,以及你本身克隆到本地電腦的倉庫,他們的關係就像下圖顯示的那樣:

若是你但願bootstrap的官方庫能接受你的修改,你就能夠在GitHub上發起一個pull request。固然,對方是否接受你的pull request就不必定了。

8.6自定義Git

8.6.1 忽略Git工做目錄中的特殊文件

在Git工做區的根目錄下建立一個特殊的.gitignore文件,而後把要忽略的文件名填進去,Git就會自動忽略這些文件。

如如下這樣,想添加一個文件到Git,但發現添加不了,緣由是這個文件被.gitignore忽略了:

$ git add App.class

The following paths are ignored by one of your .gitignore files:

App.class

Use -f if you really want to add them.
若是你確實想添加該文件,能夠用-f強制添加到Git:

$ git add -f App.class
用git check-ignore命令檢查:

$ git check-ignore -v App.class

.gitignore:3:*.class App.class
Git會告訴咱們,.gitignore的第3行規則忽略了該文件,因而咱們就能夠知道應該修訂哪一個規則。

小結

忽略某些文件時,須要編寫.gitignore;

.gitignore文件自己要放到版本庫裏,而且能夠對.gitignore作版本管理!

8.6.2 配置別名

$git config --globalalias.st status
以上命令就是給status配置了別名。git status 能夠寫成git st了。

8.6.3 搭建Git服務器

第一步,安裝git:

$ sudo apt-get install git
第二步,建立一個git用戶,用來運行git服務:

$ sudo adduser git
第三步,建立證書登陸:

收集全部須要登陸的用戶的公鑰,就是他們本身的id_rsa.pub文件,把全部公鑰導入到/home/git/.ssh/authorized_keys文件裏,一行一個。

第四步,初始化Git倉庫:

先選定一個目錄做爲Git倉庫,假定是/srv/sample.git,在/srv目錄下輸入命令:

$ sudo git init --bare sample.git
把owner改成git:

$ sudo chown -R git:git sample.git
第五步,禁用shell登陸:

出於安全考慮,第二步建立的git用戶不容許登陸shell,這能夠經過編輯/etc/passwd文件完成。找到相似下面的一行:

git: x:1001:1001:,,,:/home/git:/bin/bash
改成:

git: x:1001:1001:,,,:/home/git:/usr/bin/git-shell
第六步,克隆遠程倉庫:

$ git clone git@server:/srv/sample.git

Cloning into 'sample'...

warning: You appear to have cloned an empty repository.剩下的推送就簡單了。

相關文章
相關標籤/搜索