[TOC]
Git 快速入手
配置初始化
初次運(yùn)行 Git 前的配置
一般在新的系統(tǒng)上,我們都需要先配置下自己的 Git 工作環(huán)境。配置工作只需一次,以后升級(jí)時(shí)還會(huì)沿用現(xiàn)在的配置。當(dāng)然,如果需要,你隨時(shí)可以用相同的命令修改已有的配置。
Git 提供了一個(gè)叫做 git config 的工具,專門用來配置或讀取相應(yīng)的工作環(huán)境變量。而正是由這些環(huán)境變量,決定了 Git 在各個(gè)環(huán)節(jié)的具體工作方式和行為。這些變量可以存放在以下三個(gè)不同的地方:
- /etc/gitconfig 文件:系統(tǒng)中對(duì)所有用戶都普遍適用的配置。若使用 git config 時(shí)用 --system 選項(xiàng),讀寫的就是這個(gè)文件。
- ~/.gitconfig 文件:用戶目錄下的配置文件只適用于該用戶。若使用 git config 時(shí)用 --global 選項(xiàng),讀寫的就是這個(gè)文件。
-
.git/config 文件: 當(dāng)前工作目錄中的 .git/config 文件:這里的配置僅僅針對(duì)當(dāng)前項(xiàng)目有效。
每一個(gè)級(jí)別的配置都會(huì)覆蓋上層的相同配置,所以 .git/config 里的配置會(huì)覆蓋 /etc/gitconfig 中的同名變量。
在 Windows 系統(tǒng)上,Git 會(huì)找尋用戶主目錄下的 .gitconfig 文件。主目錄即 $HOME 變量指定的目錄,一般都是 C:\Documents and Settings$USER。此外,Git 還會(huì)嘗試找尋 /etc/gitconfig 文件,只不過看當(dāng)初 Git 裝在什么目錄,就以此作為根目錄來定位。
用戶信息
第一個(gè)要配置的是你個(gè)人的用戶名稱和電子郵件地址。這兩條配置很重要,每次 Git 提交時(shí)都會(huì)引用這兩條信息,說明是誰提交了更新,所以會(huì)隨更新內(nèi)容一起被永久納入歷史記錄:
$ git config --global user.name "heminlin"
$ git config --global user.email "heminlin@serversz.com"
如果用了 --global 選項(xiàng),那么更改的配置文件就是位于你用戶主目錄下的那個(gè),以后你所有的項(xiàng)目都會(huì)默認(rèn)使用這里配置的用戶信息。如果要在某個(gè)特定的項(xiàng)目中使用其他名字或者電郵,只要去掉 --global 選項(xiàng)重新配置即可,新的設(shè)定保存在當(dāng)前項(xiàng)目的 .git/config 文件里。
- 如何避免每次輸入密碼
如果你正在使用 HTTPS URL 來推送,Git 服務(wù)器會(huì)詢問用戶名與密碼。 默認(rèn)情況下它會(huì)在終端中提示服務(wù)器是否允許你進(jìn)行推送。
如果不想在每一次推送時(shí)都輸入用戶名與密碼,你可以設(shè)置一個(gè) “credential cache”。 最簡(jiǎn)單的方式就是將其保存在內(nèi)存中幾分鐘,可以簡(jiǎn)單地運(yùn)行 git config --global credential.helper cache 來設(shè)置它。
文本編輯器
接下來要設(shè)置的是默認(rèn)使用的文本編輯器。Git 需要你輸入一些額外消息的時(shí)候,會(huì)自動(dòng)調(diào)用一個(gè)外部文本編輯器給你用。默認(rèn)會(huì)使用操作系統(tǒng)指定的默認(rèn)編輯器,一般可能會(huì)是 Vi 或者 Vim。如果你有其他偏好,比如 Emacs 的話,可以重新設(shè)置:
$ git config --global core.editor emacs
差異分析工具
還有一個(gè)比較常用的是,在解決合并沖突時(shí)使用哪種差異分析工具。比如要改用 vimdiff 的話:
$ git config --global merge.tool vimdiff
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的輸出信息。當(dāng)然,你也可以指定使用自己開發(fā)的工具,具體怎么做可以google。
查看配置信息
要檢查已有的配置信息,可以使用 git config --list 命令:
$ git config --list
user.name=heminlin
user.email=heminlin@serversz.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...
有時(shí)候會(huì)看到重復(fù)的變量名,那就說明它們來自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不過最終 Git 實(shí)際采用的是最后一個(gè)。
也可以直接查閱某個(gè)環(huán)境變量的設(shè)定,只要把特定的名字跟在后面即可,像這樣:
$ git config user.name
heminlin
工作流程
1. 克隆遠(yuǎn)程倉庫到本地 (git clone )
做Android源碼開發(fā)時(shí),拿到芯片公司提供的Android的源碼后,我們自己的的代碼服務(wù)器上會(huì)建立一個(gè)源碼的倉庫,并會(huì)給工程師配置相應(yīng)的訪問權(quán)限。開始開發(fā)時(shí),我們首先要做的就是從服務(wù)器上獲取源碼,獲取命令如下:
$ git clone -b branch_name git@192.168.0.202:cbc/mt6735_53_v2.47.git you_dir_name
// branch_name :你需要下載的分支名字,如果運(yùn)程倉庫只有master 分支的話,這里就不用填
// you_dir_name :你本地的項(xiàng)目工作目錄名字
// git@192.168.0.202:cbc/mt6735_53_v2.47.git : 這是MT6735 代碼倉庫的地址,不同平臺(tái)的地址不一樣
//初始化時(shí)獲取E055的分支到本地E055目錄下:
$ git clone -b E055 git@192.168.0.202:cbc/mt6735_53_v2.47.git E055
$ cd E055
$ git branch
*E055
// 當(dāng)前就只有E055的分支在E055的目錄下
如果clone 的時(shí)候沒有加 -b 選項(xiàng),克隆下來的代碼將是默認(rèn)的master分支。
2. 查看修改與緩存修改 (git status, git add )
- 在修改完某個(gè)功能后,本地的代碼肯定會(huì)跟服務(wù)器的不一樣了,這時(shí)候,你需要把你的修改提交到服務(wù)器上,在提交修改之前,你首先要知道這么幾件事情:
你的工作目錄下的文件有最多有兩種類型的文件狀態(tài),一種是已經(jīng)是在跟蹤中的,另一種屬于沒有跟蹤的。
-
跟蹤中的文件又分為 已修改, 未修改,已緩存(在暫存區(qū)域) 三個(gè)狀態(tài)
//clone 完代碼到本地后,如果沒有做任何改動(dòng),那當(dāng)前目前下的所有文件都是處于 跟蹤中,都未做修改的狀態(tài), //用git status 命令可以查看到當(dāng)前目錄下所有文件的狀態(tài) $ git status # On branch E055 nothing to commit (working directory clean) // 上面是我們剛clone 下來倉庫的狀態(tài),沒有任何東西需要commit的
在我增加文件 new_file , status.txt ,修改了 AppListActivity.java 后,查看狀態(tài)顯示如下:
new_file,status.txt 兩個(gè)文件是屬于未跟蹤的文件。
查看本地修改了哪些內(nèi)容:git diff 或者查看指定文件修改了哪些內(nèi)容 git diff file_name;git diff 不會(huì)顯示未跟蹤的文件做了哪些修改。
從上圖可以看到我這里只是去掉了一行注釋。
在用 git diff 檢查完你的修改后,你就可以用add 命令緩存起來了。
從上圖可以看到已經(jīng)把AppListActivity.java提交到緩存區(qū)了。這里還顯示了2個(gè)未跟蹤的文件 new_file 和 status.txt,這兩個(gè)文件是我做測(cè)試用的,無關(guān)緊要,所以我并不需要把他們緩存起來。但如果是你新增有用的文件,比如圖片,新增的類文件等,也要用add 命令把新增的文件變成跟蹤狀態(tài),才能提交到本地倉庫。
- git add 時(shí)最好加上文件名或者目錄名,否則的話會(huì)把當(dāng)前目錄下的所有文件都添加到緩存區(qū) 上圖的git add 后面就加的是目錄名
3. 提交修改到本地倉庫(git commit)
在git status 查看到有已緩存的文件時(shí), 用 git commit 命令就可以把緩存區(qū)的文件提交到本地倉庫
$ git commit -m "修改說明"
4. 提交修改到遠(yuǎn)程倉庫 (git push)
在commit 提交修改到本地倉庫后,用git push 命令就可以把本地倉庫的分支同步到遠(yuǎn)程倉庫分支
$ git push orgin E055
// E055 是遠(yuǎn)程倉庫的名字,所以這個(gè)命令是把當(dāng)前分支同步到遠(yuǎn)程的E055分支上
5. 驗(yàn)證你提交的代碼
在代碼提交后,為保證團(tuán)隊(duì)遠(yuǎn)程倉庫代碼的正確性,最好是在另建一個(gè)本地目錄用來驗(yàn)證
$ git fetch origin
$ git rebase origin E055
$ make -j32
6.創(chuàng)建本地和遠(yuǎn)程分支
在開發(fā)過程中,為了給某個(gè)客戶開發(fā)一些定制化的功能,我們需要?jiǎng)?chuàng)建一些不同的分支,以便于維護(hù)和開發(fā)。下圖就是在本地創(chuàng)建分支E055_T并推送分支到遠(yuǎn)程倉庫的截圖。
7.打標(biāo)簽
$git tag V1.0.0 //創(chuàng)建一個(gè)輕量V1.0.0的版本標(biāo)簽
$git tag -a V1.0.0 -m "這是一個(gè)V1.0.0的版本"http:// 創(chuàng)建帶注釋的標(biāo)簽,創(chuàng)建標(biāo)簽建議用這個(gè)方式
$git tag -d V1.0.0 //刪除V1.0.0的版本標(biāo)簽
$git push --tags //把標(biāo)簽推送到遠(yuǎn)程
$git tag -l //查看標(biāo)簽 git tag 也可以
更新代碼 ( git rebase , git pull)
更新代碼有2種方式:
1.git pull origin branch_name // 這一條命令就是遠(yuǎn)程分支合并到本地分支,并更新 HEAD指針。有合并時(shí)需要輸入合并日志。
2.git fetch origin //獲取最新的倉庫代碼
git rebase origin/branch_name //把當(dāng)前分支變基到遠(yuǎn)程倉庫的最新引用上。說白了就是讓你當(dāng)前的工作分支建立了服務(wù)器最新的代碼基礎(chǔ)上。
git rebase 是變基的命令,用git rebase 后,會(huì)使你的Log 看起來是串行的,而不是并行的。
$ git checkout E055_Debug
$ git rebase E055 // 把當(dāng)前分支變基到E055的最新提交上
$ git rebase origin/E055 //把當(dāng)前分支變基到遠(yuǎn)程分支的最新引用上
上圖就是沒有用rebase 命令變基的提交記錄,可以看到不同工程師基于不同SHA-1版本的提交記錄。下圖這種串行的記錄就是用git rebase 的記錄圖,歷史修改
修改沖突
下面的幾張截圖是一個(gè)簡(jiǎn)單的沖突處理過程。
下圖是我本地做的修改,需要提交到遠(yuǎn)程倉庫,而這時(shí)候,別人也修改了這個(gè)地方,并且已經(jīng)提交到了遠(yuǎn)程倉庫,這樣我再提交的時(shí)候就會(huì)出現(xiàn)沖突。我本地做的修改如下:
查看完修改內(nèi)容后
$git add package/app
$git commit -m "沖突演示4"
$git push origin E055_Temp // 運(yùn)行這里時(shí),因?yàn)檫\(yùn)程倉庫已經(jīng)更新會(huì)提示需要更新代碼后才能提交
$git pull origin E055_Temp // 更新代碼并自動(dòng)合并到當(dāng)前分支
/* 這里建議是用組合命令來更新。
1,git fetch origin 這里是更新遠(yuǎn)程倉庫的內(nèi)容到本地
2,git rebase origin/E055_Temp // 把當(dāng)前工作分支變基到遠(yuǎn)程的最新HEAD指針上。
*/
push 的時(shí)候錯(cuò)誤:
需要更新代碼,在合并或者變基的時(shí)候會(huì)報(bào)錯(cuò):
查看當(dāng)前狀態(tài)截圖如下,可以看到有個(gè)both modified 狀態(tài)的文件
查看文件修改內(nèi)容:其中
<<<<<<< HEAD
=======
這一組符號(hào)之間的代碼表示是遠(yuǎn)程服務(wù)器上的代碼
=======
>>>>>>> 之間這段表示是你本地需要提交的修改
這兩組符號(hào)是沖突的標(biāo)志符,merge代碼的時(shí)候選擇你需要保留的代碼,然后去掉這兩組標(biāo)志符后就表示merge成功了。
按照上面的說明,我這里選擇保留我本地所做的修改,并去掉所有的<<<<<<< ====== >>>>>這些符號(hào)。修改完這個(gè)文件后,需要再add進(jìn)來,表示沖突處理完成,并再次commit。
$git add package/app/
$git rebase --contiune //如果是用的 git pull 更新的代碼,這句就不需要了
最后服務(wù)器的代碼是這樣的:
注意
上面的截圖只是一個(gè)簡(jiǎn)單的沖突處理。在實(shí)際開發(fā)過程中發(fā)生沖突時(shí),需要按照以下步驟來處理:
1.首先查看沖突的地方,選擇要保留的代碼,遇到不明白或者復(fù)雜的地方,需要找提交的工程師弄明白他所做修改的目的。
2.在修改完沖突后,需要在本地驗(yàn)證功能是否正常,有沒有影像到別人的修改。
3.驗(yàn)證完后,在執(zhí)行add,commit,push 等步驟。
撤消操作 (git reset, git checkout)

git reset 會(huì)把緩存區(qū)的改動(dòng)還原,但原來改動(dòng)的文件內(nèi)容并不會(huì)被刪除
以下是git 官方教程上的內(nèi)容:
在任何一個(gè)階段,你都有可能想要撤消某些操作。 這里,我們將會(huì)學(xué)習(xí)幾個(gè)撤消你所做修改的基本工具。 注意,有些撤消操作是不可逆的。 這是在使用 Git 的過程中,會(huì)因?yàn)椴僮魇д`而導(dǎo)致之前的工作丟失的少有的幾個(gè)地方之一。
有時(shí)候我們提交完了才發(fā)現(xiàn)漏掉了幾個(gè)文件沒有添加,或者提交信息寫錯(cuò)了。 此時(shí),可以運(yùn)行帶有 --amend 選項(xiàng)的提交命令嘗試重新提交:
$ git commit --amend
這個(gè)命令會(huì)將暫存區(qū)中的文件提交。 如果自上次提交以來你還未做任何修改(例如,在上次提交后馬上執(zhí)行了此命令),那么快照會(huì)保持不變,而你所修改的只是提交信息。
文本編輯器啟動(dòng)后,可以看到之前的提交信息。 編輯后保存會(huì)覆蓋原來的提交信息。
例如,你提交后發(fā)現(xiàn)忘記了暫存某些需要的修改,可以像下面這樣操作:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最終你只會(huì)有一個(gè)提交 - 第二次提交將代替第一次提交的結(jié)果。
取消暫存的文件
接下來的兩個(gè)小節(jié)演示如何操作暫存區(qū)域與工作目錄中已修改的文件。 這些命令在修改文件狀態(tài)的同時(shí),也會(huì)提示如何撤消操作。 例如,你已經(jīng)修改了兩個(gè)文件并且想要將它們作為兩次獨(dú)立的修改提交,但是卻意外地輸入了 git add * 暫存了它們兩個(gè)。 如何只取消暫存兩個(gè)中的一個(gè)呢? git status 命令提示了你:
$ git add *
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
modified: CONTRIBUTING.md
在 “Changes to be committed” 文字正下方,提示使用 git reset HEAD <file>... 來取消暫存。 所以,我們可以這樣來取消暫存 CONTRIBUTING.md 文件:
$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
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: CONTRIBUTING.md
這個(gè)命令有點(diǎn)兒奇怪,但是起作用了。 CONTRIBUTING.md 文件已經(jīng)是修改未暫存的狀態(tài)了。
NOTE
雖然在調(diào)用時(shí)加上 --hard 選項(xiàng)可以令 git reset 成為一個(gè)危險(xiǎn)的命令(譯注:可能導(dǎo)致工作目錄中所有當(dāng)前進(jìn)度丟失!),但本例中工作目錄內(nèi)的文件并不會(huì)被修改。 不加選項(xiàng)地調(diào)用 git reset 并不危險(xiǎn) — 它只會(huì)修改暫存區(qū)域。
到目前為止這個(gè)神奇的調(diào)用就是你需要對(duì) git reset 命令了解的全部。我們將會(huì)在 重置揭密 中了解 reset 的更多細(xì)節(jié)以及如何掌握它做一些真正有趣的事。
撤消對(duì)文件的修改
如果你并不想保留對(duì) CONTRIBUTING.md 文件的修改怎么辦? 你該如何方便地撤消修改 - 將它還原成上次提交時(shí)的樣子(或者剛克隆完的樣子,或者剛把它放入工作目錄時(shí)的樣子)? 幸運(yùn)的是,git status 也告訴了你應(yīng)該如何做。 在最后一個(gè)例子中,未暫存區(qū)域是這樣:
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: CONTRIBUTING.md
它非常清楚地告訴了你如何撤消之前所做的修改。 讓我們來按照提示執(zhí)行:
$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
可以看到那些修改已經(jīng)被撤消了。
IMPORTANT
你需要知道 git checkout -- [file] 是一個(gè)危險(xiǎn)的命令,這很重要。 你對(duì)那個(gè)文件做的任何修改都會(huì)消失 - 你只是拷貝了另一個(gè)文件來覆蓋它。 除非你確實(shí)清楚不想要那個(gè)文件了,否則不要使用這個(gè)命令。
如果你仍然想保留對(duì)那個(gè)文件做出的修改,但是現(xiàn)在仍然需要撤消,我們將會(huì)在 Git 分支 介紹保存進(jìn)度與分支;這些通常是更好的做法。
記住,在 Git 中任何 已提交的 東西幾乎總是可以恢復(fù)的。 甚至那些被刪除的分支中的提交或使用 --amend 選項(xiàng)覆蓋的提交也可以恢復(fù)(閱讀 數(shù)據(jù)恢復(fù) 了解數(shù)據(jù)恢復(fù))。 然而,任何你未提交的東西丟失后很可能再也找不到了。