公司幾乎所有的項目都是使用 git 倉庫來管理代碼,以前對 git 只有些膚淺的了解,每次提交代碼或者上線的時候總是會提心吊膽,生怕出現一些未知的問題。經過三個月的踩坑和填坑, git 操作頗顯成熟。僅以此文回憶學習 git 的歷史。
本文地址:http://www.cnblogs.com/hustskyking/p/git-improve.html,轉載請注明源地址。
一、基本操作
1. 克隆代碼
1.1 添加倉庫
最直接的方式:
cd dir # 這里不用新建一個項目名的文件夾,dir為git文件夾的父文件夾 git clone https://github.com/barretlee/Micro-Share
你也可以進入一個目錄,然后初始化(init):
cd path/to/Project git init # 添加遠程目錄 git remote add origin https://github.com/barretlee/Micro-Share
這些都是最基本的了,上面的 remote add 是添加一個遠程目錄,你也可以添加多個遠程目錄,什么情況下會添加多個呢?比如:我想把別人的代碼處理之后放到自己的 git 倉庫上去,
git remote add origin https://github.com/barretlee/Micro-Share git remote add mine http://your/path/to/git # 拉取遠程代碼到 init 之后的 master 主干上 git fetch origin master # 修改代碼之后,提交到自己的倉庫 git commit -am "fist" git push -u mine master
1.2 添加文件
在提交文件之前首先要添加文件到分支中,很多人只知道:
git add .
如果有文件刪除,會發現這些刪除的文件並沒有被附加進去,腫么辦?
#方式一 git add --all . #方式二 git add -A .
--all
參數,顧名思義,添加所有文件(change|delete|add)-A
參數,添加修改過和刪除過的文件(change|delete)- 不加 參數,添加修改過和添加的文件(change|add)
1.3 提交文件
git commit -m "comment"
如果沒有刪除過文件,可以合並添加和提交文件為一步:
git commit -am "add and commit"
1.4 遠程提交
提交到遠程倉庫上:
# 將 master 提交到 origin 上
git push origin master
這一步操作可能會出現很多的問題,比如:
a) origin為一個多人開發的庫,別人在你提交之前已經向 origin 上提交過一次(或者多次),那么此時你的版本是落后於遠程服務器版本的,你需要先拉去線上最新的代碼:
# 拉去遠程分支到 master
git pull origin master
b) 執行 a) 之后,有可能也會有提醒:存在沖突,需要合並分支,這個在后面會提到
c) 如果你很自信,覺得線上的版本是存在問題,你這個版本木有問題,你可以強制提交你的代碼
git push -u origin master -f
這里需要特別注意,加了 -f 線上之前的修改就會被刪掉,請謹慎使用!
二、進階操作指南
上面是最基本的幾條命令,初用 git 的童鞋一般也只會接觸這些東西,在一些復雜的多人開發項目中,修改代碼、合並代碼十分頻繁,上面的命令顯然是不夠用了。在介紹進階命令之前,先了解下 git 的三種狀態。
+-----------+ +-----------+ +-----------+
| | | | | |
| working | --> | index | --> | commit |
| | | | | |
+-----------+ +-----------+ +-----------+
↓ ↓ ↓
當前操作 git add git commit
<Created By Barret Lee>
你當前的操作狀態下,所有文件的狀態都在 work 狀態,當你執行 git add 之后,文件狀態變為 index,也就是在 git 中已經有過一次登記了,而 git commit 之后就被編入了分支,成為 commited 狀態了。需要注意的是,這三種狀態一直存在,只是會有不同的文件來對應這些狀態。
1. 場景切換
Barret 有一天敲代碼,代碼敲了一半,Boss 跟他說,線上出了個 bug,趕緊的,去修復!
咋辦?上面那堆代碼,敲了半個上午啊,重新新建一個文件夾,然后把線上代碼再克隆一次修改?這種處理的成本顯然太高了!其實 git 為我們提供了很好用的命令 git stash。只要在當前目錄下操作:
git stash
這句命令執行完畢之后,git 管理區中的 stash 會多出一條記錄,這條記錄保存了上一次提交到目前,你所有的修改:
last commit ... working file now
接着你就可以修改你的 bug 了,修改完了之后,再使用
git stash pop
將之前保存的修改(場景)還原回來。其內部的原理也是很簡單的:
+---------------+ +-----------+ +-----------+ +-----------+ | | | | | | | | | last commit | --> | working | --> | index | --> | commit | | | | | | | | | +---------------+ ↑ +-----------+ +-----------+ | +-----------+ ↓ | ↓ ↓ | ↓ 上次提交 | 當前操作 git add | git commit | s| | t| | +---------+ a| | | Stash 0 | s| | +---------+ h| +------ | Stash 1 | <------------------+ +---------+ | .... | +---------+ | Stash n | +---------+ ↓ <Created By Barret Lee> stash堆棧
有些童鞋可能看不太懂上面的圖,git 有一個場景(stash)堆棧,這個堆棧的作用是用於保存修改的,下面舉個例子:
# 進入文件夾 $ cd test # 初始化 git $ it init # 新建四個文件 $ touch f1 f2 f3 f4
上面初始化一個 git ,然后新建了四個文件
# 修改 f1 $ echo "1" > f1 # 將修改 push 到 stash 棧堆中 $ git stash
上面修改了文件 f1,並保存到場景棧堆中
# 查看 stash 棧堆 $ git stash list stash@{0}: WIP on master: 7f58be2 3
查看棧堆,可以看到 stash@{0}
# 修改 f2 $ echo "1" > f2 # 添加修改 $ git add . # 將修改 push 到 stash 棧堆中 $ git stash
修改文件 f2,添加之后保存到棧堆之中
# 查看 stash 棧堆 $ git stash list stash@{0}: WIP on master: 7f58be2 3 stash@{1}: WIP on master: 7f58be2 3
棧堆中多了一個 stash@{1},這個時候我們去修復 bug,改變其他位置的代碼,完了之后:
# pop 棧堆,還原修改
$ git stash pop
上面我們將棧堆 pop 出來,遵循后進先出的規則
# 查看文件狀態 git status $ Changes not staged for commit: changed: f2 please commit it
以上代碼都是我手動敲出來的,不是復制控制台的代碼,大概就是這個么意思吧。關於 stash 的最后一個想說明的命令是:
git stash clear
清空場景(stash)堆棧。
2. 代碼 diff
2.1 HEAD
在介紹這塊之前,也需要先了解幾個基本的常識:
HEAD 它表示上一次的 commit 版本
HEAD~n 它表示第上 n 詞的 commit 版本,這里的 n 是大於等於 1 的整數
如果我們要比較上一次和這一次代碼之間的差異,可以:
git diff HEAD~1 HEAD
比較前第三次與現在代碼的差異,可以:
git diff HEAD~3 HEAD
獲取前第n次的還有另外一種方式,如前第二次:
HEAD^^
前第五次:
HEAD^^^^^
這樣寫起來比較累,還是前面的方式比較順手。
2.2 SHA
關於 SHA 標識的介紹,我這里就懶得打字了,可以看我之前分享的一點東西,使用
git log
可以看到每次 commit 的 SHA 標識。要比較兩次提交之間的差異,可以直接
git diff SHA1 SHA2
其中 SHA1 和 SHA2 是兩次提交(commit)時的標識。
2.3 與場景的比較
這個用的比較少,對比目前代碼跟最近一次 push 的場景代碼差異:
git diff --cached
從字面上也好理解,就是跟緩存的文件做對比嘛~
3. 版本回退
如果上面的 SHA,working,index,commit 幾種狀態和標識沒有弄明白,相信這里也是十分難理解的。
版本回退使用的命令是:
git reset
3.1 三種操作
這個命令后面是要加參數的,分別為:
a) filename
git reset HEAD filename # 從暫存區移除文件
如果之前有 add filename,上面的命令操作之后,filename 將處於未被 add 的狀態。也就是從 index 轉變成 working 狀態。
b) HEAD
git reset --hard HEAD~n
直接回退到前第 n 個版本。
c) SHA
git reset --hard SHA
回到 SHA 對應的 commit 的版本。
3.2 三種方式
上面我們使用的是 --hard
來 reset 代碼,這樣風險是特別大的,這里有三個可選參數:
--hard
回退版本,代碼也回退,忽略所有修改--soft
回退版本,代碼不變,回退所有的 add 操作--mixed
回退版本,代碼不變,保留 add 操作
4. 分支處理
4.1 查看分支
git branch
這是最簡單的查看,查看本地創建了哪些分支。
git branch -va
查看本地+遠程分支,及其詳細信息(上次提交commit信息)
4.2 添加分支
git branch branch_name
如果你當前所在的分支是 master,此處創建的分支會直接繼承 master 的所有修改歷史。
git branch -b branchnew branchold
-b
是 base 的意思,如果你有兩個分支 A 和 B ,目前在 A 分支上,你先新建一個分支繼承 B,此刻你有兩個選擇:
# 選擇一
# 先切換到 B 分支上
git checkout B
git branch C
# 選擇二
git branch -b C B
4.3 切換分支
a) 切換到本地分支
git checkout branch_name
b) 切換到遠程分支
git checkout remotes/origin/branch_name
git checkout branch_name
詳情請看之前分享的這篇文章,git切換到遠程分支
4.4 刪除分支
顯切換到別的分支上,然后
git branch -d branch_name
如果是遠程分支:
git push origin :branch_name
在需要刪除的分支前面加一個冒號OK了,push 上去之后,服務器上的分支自然就被刪除了。
由於想寫的內容實在太長,故打算下次再補充第二部分。
下期預告:
本節補充:
5. tag處理
6. 倉庫管理
第三章 版本管理策略
第四章 看懂 diff
第五章 配置別名
下次再做小結。