本文轉載自:http://igeekbar.com/igeekbar/post/82.htm
Git近些年的火爆程度非同一般,這個版本控制系統被廣泛地用在大型開源項目(比如Linux),不同規模的團隊開發,以及獨立開發者,甚至學生之中。
初學者非常容易被git里的各種命令、參數嚇得不願意繼續去學。但實際上剛上手的時候,你並不需要了解所有命令的用途。你可以從掌握一些簡單、常用又強大的命令開始,然后逐步去學習。這就是我們這篇文章要講的內容。讓我們快開始吧!
基本了解
Git是一些命令行工具的集合,可以用來跟蹤、記錄文件的變動,經常用於開源代碼。比如你可以進行舊版本恢復、比對、分析、合並等等。這個過程被稱之為版本控制。已經有一系列的版本控制系統,比如SVN、Mercurial、Perforce、CVS、Bitkeepe等等。
Git是分布式的,這意味着它並不依賴於中心服務器來保存你文件的舊版本。任何一台機器都可以有一個本地版本的控制系統,其實就是一個硬盤上的文件,我們稱之為倉庫(repository)。如果是多人協作的話,你還需要一個線上倉庫,用來同步代碼等信息。這就是GitHub、BitBucket等網站做的工作。
1.安裝Git
在你的機器上安裝git非常簡單:
- Linux – 打開終端,然后通過包管理安裝,在Ubuntu上命令是:sudo apt-get install git
- Windows – 推薦使用git for windows,它包括了圖形工具以及命令行模擬器。
- OS X – 最簡單的方式是使用homebrew安裝,命令行執行brew install git
如果你是新手,推薦使用圖形工具Github desktop和Sourcetree。不過即使使用圖形界面的應用,知道一些基本的git命令依然很重要。接下來的內容我們集中在命令行控制上。
2.配置Git
安裝完git,首要任務是做一些簡單的配置,最重要的是用戶名及郵箱,打開終端,執行以下命令。
$ git config --global user.name "My Name"
$ git config --global user.email myEmail@example.com
配置好這兩項,Git就能記錄下來是誰做的動作,一切都更有組織性了。
3.創建一個新倉庫 – git init
git會把所有文件以及歷史記錄直接記錄成一個文件夾保存在你的項目中。創建一個新的倉庫,首先要去到項目路徑下,執行git init。這時Git會創建一個隱藏的文件夾.git,所有的歷史和配置信息都儲存在其中。
比如我們在桌面創建一個文件夾 git_exercise, 打開終端,輸入:
$ cd Desktop/git_exercise/
$ git init
命令行會出現
Initialized empty Git repository in /home/user/Desktop/git_exercise/.git/
這說明我們的倉庫已經建立好了,但現在是空的,試着新建一個hello.txt文本文件到這個文件夾里。
4.檢查狀態 – git status
Git status是另一個非常重要的命令,它反饋給我們倉庫當前狀態的信息:是否為最新代碼,有什么更新等等。在我們新建的倉庫中執行git status會得到以下內容:
$ git status
On branch master
Initial commit
Untracked files:
(use "git add ..." to include in what will be committed)
hello.txt
反饋信息告訴我們,hello.txt尚未跟蹤,這是說這個文件是新的,git不知道是應該跟蹤它的變動還是直接忽略。為了跟蹤我們的新文件,我們需要暫存它。
5.暫存 – git add
Git有個概念叫“暫存區“,你可以把它看成一塊空白的畫布,包裹着所有你可能會提交的變動。它一開始是空的,可以通過 git add 命令添加內容,最后使用 git commit 提交(創建一個快照)。
這個例子中只有一個文件,讓我們先add它:
$ git add hello.txt
如果需要提交目錄下的所有內容,可以這樣做:
$ git add -A
再次使用git status查看狀態試試:
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: hello.txt
我們的文件已經准備好可以提交了。狀態信息還告訴我們暫存區文件發生了什么變動,這里我們新增了一個文件,同樣可以做修改和刪除。取決於我們在上一次git add之后發生了什么。
6.提交 – git commit
一次提交代表着我們的倉庫到了一個新的狀態,就像是一個快照,允許我們像使用時光機一樣回到之前的某個時間點。
創建提交,需要我們至少在到暫存區有一次修改(剛才我們做了git add),然后輸入命令:
$ git commit -m "Initial commit."
這就創建了一次從暫存區的提交(加入hello.txt),-m “Initial commit.”是用戶對這次提交的描述,建議寫成有意義的描述性信息。
遠程倉庫
到目前為止,我們的操作都是在本地的——只存在於.git文件中。為了能夠協同開發,我們需要把代碼部署到遠程倉庫服務器上。
1.鏈接遠程倉庫 – git remote add
為了能夠上傳到遠程倉庫,我們需要先建立起鏈接。在這篇教程中,我們遠程倉庫的地址為:https://github.com/igeekbar/awesome-project。但你應該自己在Github、或BitBucket上搭建倉庫,自己一步一步嘗試。
把本地倉庫鏈接到Github上,在命令行執行以下內容:
# This is only an example. Replace the URI with your own repository address.
$ git remote add origin https://github.com/igeekbar/awesome-project.git
一個項目可以同時擁有好幾個遠程倉庫,為了區分通常會起不同的名字。通常主要的遠程倉庫被稱為origin。
2.上傳到服務器 – git push
把本地的提交傳送到服務器的動作叫做push。每次我們要提交修改到服務器上時,都會使用到git push。
git push命令有兩個參數,遠程倉庫的名字,以及分支的名字:
$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 212 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/igeekbar/awesome-project.git
* [new branch] master -> master
取決於你使用的服務器,push過程中你可能需要驗證身份(輸入用戶名、密碼,請先在網站上進行注冊)。如果沒有出差錯,現在用瀏覽器看你的遠程倉庫上已經有hello.txt了。
3.克隆倉庫 – git clone
其他人可以看到你放在Github上的開源項目,他們可以用git clone命令下載到本地。
$ git clone https://github.com/igeekbar/awesome-project.git
本地也會創建一個新的倉庫,並自動將github上的版本設為遠程倉庫。
4.從服務器上獲得修改 – git pull
如果你更新了遠程倉庫上的內容,其他人可以通過git pull命令拉取你的變動:
$ git pull origin master
From https://github.com/igeekbar/awesome-project
* branch master -> FETCH_HEAD
Already up-to-date.
因為在我們git clone之后還沒有提交過修改,所有沒有任何變動。
分支
當你在做一個新功能的時候,最好是在一個獨立的區域上開發(原始項目的拷貝),通常稱之為分支。分支之間相互獨立,並且擁有自己的歷史記錄,直到你決定把他們合並到一起。這樣做的原因是:
- 已經可以運行的穩定版本的代碼不會被破壞
- 不同的功能可以由不同開發者同時開發
- 開發者可以專注於自己的分支,不用擔心被其他人破壞
- 在不確定哪個版本更好之前,同一個特性可以在不同的分支上創建多個版本,便於比較
1.創建新分支 – git branch
每一個倉庫的默認分支都叫master, 創建新分支可以用git branch <name>命令:
$ git branch amazing_new_feature
創建了一個名為amazing_new_feature的新分支,它目前和master分支是一樣的內容。
2.切換分支 – git checkout
使用git branch,可以查看分支狀態:
$ git branch
amazing_new_feature
* master
* 號表示當前活躍分支為master,現在我們想在新分支上開發新的特性,使用git checkout切換分支。有一個參數表示要切換到的分支。
$ git checkout amazing_new_feature
3.合並分支 – git merge
我們在“amazing_new_feature”分支想添加一個feature.txt。和之前一樣我們來創建文件、添加到暫存區、提交。
$ git add feature.txt
$ git commit -m "New feature complete."
新分支任務完成了,回到master分支。
$ git checkout master
現在去查看文件夾內容,你會驚奇地發現之前剛剛創建的feature.txt文件不見了,因為我們現在回到了master分支上,這里並沒有feature.txt。想把文件添加到這里,我們需要使用git merge把amazing_new_feature分支合並到master上。
$ git merge amazing_new_feature
現在master分支是最新的了,amazing_new_feature分支可以刪掉了。
$ git branch -d amazing_new_feature
進階功能
在這篇教程的最后一節,我們來看一些高級並且實用的技巧。
1.比對兩個不同提交之間的差別
每次提交都有一個標識id,查看所有歷史提交和他們的id,可以使用 git log:
$ git log
commit ba25c0ff30e1b2f0259157b42b9f8f5d174d80d7
Author: igeekbar
Date: Fri July 29 17:15:28 2016 +0300
New feature complete
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author: igeekbar
Date: Fri July 29 16:30:04 2016 +0300
Added content to hello.txt
commit 09bd8cc171d7084e78e4d118a2346b7487dca059
Author: igeekbar
Date: Thu July 28 17:52:14 2016 +0300
Initial commit
id很長,但是當使用它的時候你並不需要復制整個字符串,前幾個字符就夠了。
查看某一次提交更新了什么,使用 git show [commit]:
$ git show b10cc123
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author: igeekbar
Date: Fri July 29 16:30:04 2016 +0300
Added content to hello.txt
diff --git a/hello.txt b/hello.txt
index e69de29..b546a21 100644
--- a/hello.txt
+++ b/hello.txt
@@ -0,0 +1 @@
+Nice weather today, isn't it?
查看兩次提交的不同,可以使用git diff [commit-from]..[commit-to]:
$ git diff 09bd8cc..ba25c0ff
diff --git a/feature.txt b/feature.txt
new file mode 100644
index 0000000..e69de29
diff --git a/hello.txt b/hello.txt
index e69de29..b546a21 100644
--- a/hello.txt
+++ b/hello.txt
@@ -0,0 +1 @@
+Nice weather today, isn't it?
比較首次提交和最后一次提交,我們可以看到中間所有的更改。使用git difftool命令可以用圖形化界面查看所有更改。
2.回滾某個文件到之前的版本
Git允許我們將某個特定的文件回滾到特定的提交,使用的也是 git checkout命令。
下面我們將hello.txt回滾到最初的狀態,需要指定回滾到哪個提交(以id作為參數),以及文件的全路徑。
$ git checkout 09bd8cc1 hello.txt
3.回滾提交
如果你發現最新的一次提交忘記加入某個文件,或是信息輸入的不正確,你可以通過 git commit --amend來改正,它會把最新的提交打回暫存區,並嘗試重新提交。
如果是更復雜的情況,比如不是最新的提交除了問題,你可以使用git revert。
最新的一次提交別名也叫HEAD。
$ git revert HEAD
其他提交需要指明id:
$ git revert b10cc123
回滾提交時,發生沖突是非常頻繁的。比如文件被指定回滾的提交之后的某次提交修改過,git不能正確回滾。
4.解決合並沖突
沖突經常出現在合並分支或者是拉取別人的代碼。有些時候git能自動處理沖突,其他時候需要我們手動處理。
我們來看以下的例子,John 和 Tim 分別在各自的分支上寫了一段代碼,來顯示一個數組中所有的元素。
John使用了for循環:
// Use a for loop to console.log contents.
for(var i=0; i<arr.length; i++) {
console.log(arr[i]);
}
Tim使用forEach:
// Use forEach to console.log contents.
arr.forEach(function(item) {
console.log(item);
});
它們都提交了代碼到各自的分支上,現在假設John嘗試合並Tim的代碼:
$ git merge tim_branch
Auto-merging print_array.js
CONFLICT (content): Merge conflict in print_array.js
Automatic merge failed; fix conflicts and then commit the result.
這時候git並不能自動解決沖突,於是它在代碼中插入沖突標記。
<<<<<<< HEAD
// Use a for loop to console.log contents.
for(var i=0; i<arr.length; i++) {
console.log(arr[i]);
}
=======
// Use forEach to console.log contents.
arr.forEach(function(item) {
console.log(item);
});
>>>>>>> Tim’s commit.
==== 號上方是當前最新一次提交,下方是沖突的代碼。這樣我們可以清晰地看出區別,決定使用哪一個版本,或者重新寫一個。假設我們對於這兩個版本都不滿意,我們把代碼改成以下代碼:
// Not using for loop or forEach.
// Use Array.toString() to console.log contents.
console.log(arr.toString());
好了,再提交一下:
$ git add -A
$ git commit -m "Array printing conflict resolved."
在大型項目中,我們可能在合並過程中出現很多沖突,大部分開發者會借助GUI工具來獲得幫助,運行推行界面可以使用git mergetool命令。
5.配置 .gitignore
大部分項目中,會有些文件、文件夾是我們不想提交的。為了防止使用git add -A時不小心提交,我們可以利用.gitignore文件:
- 在項目根目錄創建.gitignore文件
- 在文件中列出不需要提交的文件名、文件夾名,每個一行
- .gitignore文件需要像普通文件一樣add、commit和push
通常會被ignore的文件有:
- log文件
- task runner builds
- node.js項目中的node_modules文件夾
- IDEs比如NetBeans和IntelliJ生成的文件
- 個人筆記
以下是一個.gitignore文件的例子:
*.log
build/
node_modules/
.idea/
my_notes.txt
“/”說明是一個文件夾,里面的所有內容都被遞歸忽略
總結
Git教程到這里就結束啦!
Git很復雜,還有很多的特性和技巧等着你去挖掘,這篇教程只涵蓋了冰山一角,希望你不要因為太多繁瑣的命令而停下前進的腳步!加油!
via: tutorialzine.com