Git近年來受到歡迎。版本代碼控制系統被Linux等巨大的開源項目所使用,成千上萬的貢獻者,各類規模的團隊,獨立開發者,甚至是學生。node
初學者經常被git所要求的全部神祕的命令和參數所嚇倒。面試常常也會問到git 命令。你能夠開始掌握一些最經常使用的,而後從在慢慢進一步學習。linux
Git是一個命令行實用程序的集合,它會跟蹤和記錄文件中的更改(一般是源代碼,可是能夠跟蹤任何你想要的文件)。 有了它,你能夠恢復項目的舊版本,比較,分析,合併更改等操做。 這個過程被稱爲版本控制。 有許多版本控制系統能夠完成這項工做。 你可能據說過其中的一些--SVN,Mercurial,Perforce,CVS,Bitkeeper等等。 Git是分散的,這意味着它不依賴於中央服務器來保留文件的舊版本。 相反,它徹底在本地運行,將這些數據做爲一個文件夾存儲在硬盤上,咱們稱之爲儲存倉庫。 可是,你也能夠在線存儲您的倉庫的副本,這使得多我的能夠輕鬆協做並使用相同的代碼。這就是像GitHub和BitBucket這樣的網站所使用的同樣。git
在你的設備上安裝Git很簡單: Linux - 只需打開一個新的終端,並經過發行版的軟件包管理器安裝git。 對於Ubuntu的命令是: sudo apt-get install git Windows - 咱們推薦 git for windows, 由於它提供了一個GUI可視化客戶端和一個BASH命令行模擬器。 OS X - 最簡單的方法是安裝 自助軟件,而後brew install git從終端 運行。 若是你是一個絕對的初學者,那麼一個圖形化的git客戶端是必須的。 我強烈推薦使用GitHub Desktop和Sourcetree,可是還有許多其餘好的和免費的在線。 即便使用GUI應用程序,瞭解基本的git命令仍然很重要,所以在本文剩下的部分中,這將是咱們惟一說的重點。github
如今咱們已經在咱們的計算機上安裝了git,咱們將須要添加一些快速配置。 有不少能夠擺弄的選項,可是咱們要設置最重要的選項:咱們的用戶名和電子郵件。 打開一個終端並運行這些命令:面試
$ git config --global user.name "My Name"
$ git config --global user.email myEmail@example.com
複製代碼
咱們在Git中所作的每個動做如今都會貼上咱們的名字和地址。 這樣用戶老是知道誰作了什麼,一切都更有條理。windows
正如咱們前面提到的,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的簡單文本文件,並將其保存在git_exercise文件夾中。安全
4.檢查狀態 - git statusbash
Git status 是另外一個必須知道的命令,它返回關於倉庫當前狀態的信息:一切是最新的信心,那些是最新的,哪些是改變的,等等。 運行git status 在咱們新建立的Log應該返回如下內容:
$ git status
On branch master
Initial commit
Untracked files: (use "git add ..." to include in what will be committed)
hello.tx
複製代碼
返回的消息指出hello.txt未被跟蹤。這意味着文件是新的,Git不知道它是否應該跟蹤發生在這個文件上的變化,或者忽略它。爲了確認新文件,咱們須要對其進行分類。
5.添加 - git add Git有一個「暫存區」的概念。你能夠把它想象成一個空白的畫布,它保存着你想要提交的變化。它開始是空的,但你能夠用命令添加文件(甚至是單行和部分文件)git add,最後提交全部的文件(建立一個快照)git commit。 文件:
$ 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 commmit"部分是用戶自定義的描述,總結了在該提交中所作的更改。 常常提交併老是編寫有意義的提交消息,被認爲一個開發者的好習慣。
遠程倉庫
如今咱們的提交是本地的 - 它只存在於.git文件夾中。雖然本地存儲庫自己是有用的,但在大多數狀況下,咱們都但願共享咱們的工做並將其部署到服務器或存儲庫託管服務。
爲了上傳東西到一個遠程的響應,咱們首先必須創建一個鏈接。 爲了配合本文,咱們的存儲庫的地址將是https://github.com/Tamic/novate。 咱們建議放在在GitHub,BitBucket或任何其餘服務中建立本身的空存儲庫。 註冊和設置可能須要等待一段時間,但全部服務都提供了很好的分步指南文檔來幫助你。
要將咱們的本地存儲庫與GitHub上的存儲庫鏈接起來,咱們在終端中執行如下行: 文件:
# 鏈接到遠程服務器
$ git remote add origin https
:
//github.com/Tamic/novate.git
複製代碼
項目可能同時擁有多個遠程倉庫。爲了可以區分他們,咱們給他們不一樣的名字。 傳統上git中的主遠程倉庫被稱爲origin。
如今是時候把咱們的本地提交轉移到服務器上了。 這個過程被稱爲推送(push),而且每當咱們想要更新遠程倉庫就完成了。 Git命令是這樣作的,git push而且須要兩個參數 - 遠程回購(咱們稱之爲咱們的 產地)的名稱和推到的分支(master是每一個反饋的默認分支)。
$ 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/Tamic/novate.git *
[new branch ] | master -> master
複製代碼
根據你使用的遠程服務,你將須要驗證本身的密碼和帳號。 若是一切正常完成,當你在你的網絡瀏覽器中進入前面建立的遠程倉庫時, hello.txt 應該在那裏,而且能夠打開閱讀。
此時,你們能夠在Github上查看和瀏覽遠程倉庫庫。他們能夠在本地下載,並使用如下git clone命令得到項目的完整工做副本:
$ git push origin master
$ git clone https
:
//github.com/Tamic/novate.git
複製代碼
自動建立一個新的本地倉庫,並將github版本配置爲遠程。
若是你的代碼倉庫進行了更新,則可使用下面單個命令下載更改 - git pull:
$ git pull origin master
From
https
:
//github.com/Tamic/novate.git
*
branch master
->
FETCH_HEAD
Already
up
-
to
-
date
.
複製代碼
因爲咱們克隆的沒有 沒有其餘人提交新的文件或者修改,下載時候提示沒有任何變化。
在開發一個新功能時,考慮一個原始項目的副本,稱爲分支,也被認爲開發者的一個好習慣 。分支有他們本身的歷史記錄,並將他們之間的變化隔離開來,直到你決定把它們合併在一塊兒。 這是因爲如下幾個緣由:
一個已經工做,穩定的代碼版本不會被破壞。 許多功能能夠由不一樣的人本身立馬並能安全穩定的開發。 開發人員能夠在本身的分支上工做,而不會由於別人的工做而改變代碼庫的風險。 當不肯定什麼是最好的時候,能夠在不一樣的分支上開發相同特徵的多個版本,而後進行比較。
每一個存儲庫的默認分支稱爲 主(Master)分支。 要建立更多分支,請使用如下git branch 命令:
$ git branch amazing_new_feature
複製代碼
這只是建立了新的分支,在這一點上是徹底同樣的,咱們的主幹。
2.切換分支 - git checkout
如今,當咱們運行時git branch,咱們會看到有兩個選項可用:
$ git branch
amazing_new_feature
*
master
複製代碼
Master是當前分支,並標有星號。可是,咱們想要使用咱們的新功能,因此咱們須要切換到另外一個分支。這是用git checkout命令完成的,須要一個參數 - 要切換到的分支名稱。
$ git checkout amazing_new_feature
複製代碼
git的「驚人的新功能」將成爲另外一個名爲feature.txt的文本文件。 咱們將建立它,add它,並commit。
$ git add feature.txt
$ git commit -m 「新功能完成」。
複製代碼
新功能完成後,咱們能夠切回到主分支。
$ git checkout master
複製代碼
如今,若是咱們在文件瀏覽器中打開咱們的項目,咱們會注意到feature.txt 已經消失了。那是由於咱們回到了master分支,而這裏feature.txt 歷來沒有被建立過。爲了實現這個目標,咱們須要將這git merge兩個分支結合在一塊兒,將在 amazing_new_feature中完成的更改應用於項目的主版本。
git合併amazing_new_feature
複製代碼
主分支如今是最新的。awesome_new_feature分支再也不須要,能夠刪除。
git branch -d amazing_new_feature
複製代碼
在本文的最後一節中,我將介紹一些更高級的技術,這些技術極可能在你工做中派上用場。 1.檢查提交之間的差別 每一個提交都以數字和符號的字符串形式存在惟一的ID。 要查看全部提交及其ID的列表,咱們可使用git log:
$ git log
commit ba25c0ff30e1b2f0259157b42b9f8f5d174d80d7
Author
:
Tutorialzine
Date
:
Mon
May
30
17
:
15
:
28
2016
+
0300
New
feature complete
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author
:
Tutorialzine
Date
:
Mon
May
30
16
:
30
:
04
2016
+
0300
Added
content to hello
.
txt
commit
09bd8cc171d7084e78e4d118a2346b7487dca059
Author
:
Tutorialzine
Date
:
Sat
May
28
17
:
52
:
14
2016
+
0300
Initial
commit
複製代碼
正如你所看到的,ID是很長的,可是和它們一塊兒工做時,沒有必要複製整個東西 - 前幾個符號一般就足夠了。
要查看提交中的新增內容,咱們能夠運行git show [commit]:
$ git show b10cc123
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author
:
Tutorialzine
Date
:
Mon
May
30
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命令能夠更容易地完成這個任務,這個命令可讓一個圖形化的客戶端顯示全部的差別。
Git容許咱們將任何選定的文件返回到某個提交中的方式。這是經過git checkout 咱們之前用來切換分支的熟悉的命令完成的,可是也能夠用來在提交之間切換(在Git中一個命令用於多個看起來不相關的任務是很常見的)。 在下面的例子中,咱們將採用hello.txt,並將自從初始提交以來所作的一切都撤銷。 要作到這一點,咱們必須提供咱們想要返回的提交的id,以及咱們文件的完整路徑。
$ git checkout 09bd8cc1 hello.txt
複製代碼
若是你注意到你在提交信息中輸入了一個錯字,或者你忘記了添加一個文件,而且在提交以後你看到了,你能夠很容易地解決這個問題git commit --amend。這將添加從上次提交到暫存區域的全部內容,並嘗試進行新的提交。這給你一個機會來解決你的提交信息或添加更多的文件到臨時區域。
對於不在上次提交中的更復雜的修復(或者若是您已經推送了更改),則必須使用git revert。 這將採起提交引入的全部更改,將其回滾,並建立一個與此相反的新提交。
最新的提交能夠被HEAD別名訪問。
$ git revert HEAD
對於其餘提交,最好使用一個id。 $ git revert b10cc123
當恢復較舊的提交時,請記住合併衝突極可能會出現。 當一個文件被另外一個更近的提交改變時,會發生這種狀況,如今Git找不到正確的行來恢復,由於它們不在那裏了。
除了前面所描述的狀況以外,在合併分支或者牽扯其餘人的工做時常常出現衝突。 有時候,衝突是由git自動處理的,但有時候處理這些衝突的人必須決定(一般是精選)哪些代碼保留,什麼被刪除。
咱們來看一個例子,我會合並兩個叫作john_branch和tim_branch的分支。 小張和小李都在同一個文件中寫入一個顯示數組中全部元素的函數。
小張正在使用for循環:
//使用for循環到console.log內容。
for(var i = 0;
i
<
arr
.
length
;
i
++){
console
.
log
(
arr
[
i
]);
}
小李喜歡
forEach
:
//使用forEach到console.log內容。
arr
.
forEach
(
function
(
item
)
{
console
.
log
(
item
);
});
他們都在各自的分支上提交代碼。
如今,若是他們嘗試合併兩個分支,他們將看到如下錯誤消息:
$ 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沒法自動合併分支,因此如今由開發人員手動解決衝突。 若是他們打開衝突所在的文件,他們會看到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
);
});
>
>>>>>> xiaozhang's commit. 複製代碼
在=====之上,咱們有當前的HEAD提交,而且在衝突之下。 這樣咱們就能夠清楚地看到差別,並決定哪一個版本更好,或者一塊兒寫一個新版本。 在這種狀況下,咱們去找後者,重寫整個事情,刪除標記讓Git知道咱們已經完成了。 //不使用循環或forEach。 //將Array.toString()用於console.log內容。 console . log ( arr . toString ());
m "解決衝突." 正如你所看到的,這個過程很是煩人,在大型項目中可能會遇到很大的困難。 大多數開發人員傾向於在GUI客戶端(下載https://git-scm.com/download/gui/linux) 的幫助下解決衝突,這使事情變得更容易。運行圖形客戶端使用git mergetool。
在大多數項目中都有咱們不想提交的文件或整個文件夾。 咱們能夠git add -A 經過建立.gitignore文件來確保它們不會被意外地包含在咱們 的內容中: 手動建立一個名爲.gitignore的文本文件,並將其保存到項目目錄中。 在裏面,列出要忽略的文件/目錄的名稱,每一個都在一個新的行上。 .gitignore自己必須被添加,提交和推送,就像項目中的任何其餘文件同樣。 很好的文件被忽略的例子是: 日誌文件 任務運行者創建 node.js項目中的node_modules文件夾 由NetBeans和IntelliJ等IDE建立的文件夾 我的開發者筆記
禁止上述全部內容的.gitignore將以下所示: *.
log
build
/
node_modules
/
.
idea
/
my_notes
.
txt
複製代碼
在某些行末尾的斜線表示這是一個文件夾,咱們忽略了遞歸中的全部內容。星號一般用做通配符。
Git至關複雜,並提供更多的功能和技巧。若是你想了解更多 推薦的學習資源: 官方的Git文檔,包括一整本書和視頻課程 -在這裏(git-scm.com/doc)。 讓git正確 - Atlassian收集的教程和文章 -在這裏(www.atlassian.com/git/)。 一個GUI客戶端列表 -在這裏(www.git-scm.com/downloads/g… Git備忘單(PDF) -這裏。 services.github.com/on-demand/d…
生成.gitignore文件的在線工具 -在這裏。 www.gitignore.io/