前言
- Git相關操作總結
- 2018-7-14, 聯(lián)創(chuàng)團隊分享
- 文中部分圖片見文末參考鏈接
正文
一. 基本概念
版本控制
- 本地版本控制: 單機
- 集中式版本控制系統(tǒng): 多人合作; 中央服務器;需要聯(lián)網(wǎng)(查看提交歷史等)
- 分布式版本控制系統(tǒng): 多人合作; 每一個客戶端都是一個完整的倉庫鏡像
- 集中式與分布式區(qū)別: 集中式中由中央服務器保存所有的提交記錄,存在宕機和數(shù)據(jù)丟失風險,常見如:SVN;分布式中,不用擔心因為服務器故障造成的數(shù)據(jù)丟失,常見如:Git
幾個基本概念
- 工作區(qū)(Working): 就是平時我們可見的部分,一般是對項目中某個版本獨立提取出來
- 暫存區(qū)(索引)(Stage): 保存了下一次將提交的文件列表信息
- Git倉庫(.git): 是最重要的部分,我們所有的操作(版本控制,提交歷史等)都基于Git倉庫
-
為了理解的更形象,可以結合下面這張圖,將一個版本庫劃分為三個部分
文件的幾個狀態(tài)
- 未跟蹤(Untracked): 從未add的文件
- 已修改(Modified): 修改了一個已add文件之后,還未重新add(處于工作區(qū))
- 已暫存(Staged): 修改了一個文件,并add,但是還未commit(處于暫存區(qū))
- 已提交(Commited): 修改了一個文件之后,add并commit(處于版本庫)
HEAD與分支
- HEAD: 一個指針,始終指向當前活躍分支
- 分支: 實際上也是一個可變指針,始終指向最后一次commit的對象,沒commit一次,分支就前進一次
- 話不多說,看圖
-
分支始終指向該分支上最近一次commit
-
HEAD始終指向當前分支
- master
每次創(chuàng)建倉庫的時候,都會默認創(chuàng)建的一個分支
- HEAD^, HEAD^^, HEAD~100
- HEAD^ : 表示上一個版本
- HEAD^^ : 表示上兩個版本
- HEAD~100: 表示上100個版本(當然,如果不閑麻煩的話,也可以寫100個
^
)- 所謂的上一次,即在當前分支上,按照提交順序區(qū)分的
二. 基本操作
git status
基本輸出如下:
2.首先能夠看出的信息是當前處于哪個分支上,接下來是上面所介紹的文件處于什么狀態(tài),然后是一些命令提示,可以怎么操作,基本比較簡單
-
git status -s : 簡化命令輸出;只輸出文件狀態(tài)
-
git status -sb: 簡化命令輸出;只輸出當前所處分支和文件狀態(tài)(這個命令比較形象...:)
git log
- 查看提交日志,確切的說查看當前分支之前的提交日志
- git log --oneline: 簡化輸出
- git log --graph: 圖形界面輸出
- git --oneline --graph: 合用
- git log -p [-n]: 可以查看每一步完整的提交區(qū)別,使用
-n
參數(shù),表示顯示最近n次 - git reflog : 記錄每一次命令,這個操作主要是用于當回退到某一版本的時候,想要回到未回退前的版本,但是這時候用
git log
只能顯示出當前版本之前commit id,看不到回退前的commit id,此時就可以用此命令查看命令歷史
撤銷操作
我們平時所需要用到的撤銷操作主要是針對: 工作區(qū)內(nèi)容撤銷,暫存區(qū)內(nèi)容撤銷,分支上的版本回退;分別對應文件所處的幾種狀態(tài)
- 工作區(qū)內(nèi)容撤銷
- 主要用于當工作區(qū)內(nèi)容被誤修改或者無效修改時,需要清除修改的工作區(qū)內(nèi)容,但是該操作需謹慎,因為無法恢復
- git checkout -- file : 撤銷對file文件在工作區(qū)的修改;如果想要一次性撤銷對工作區(qū)的內(nèi)容修改,可以使用通配符,
git checkout -- .
- 需要注意的是該操作只對已追蹤文件起作用,對于未追蹤的文件(Untracked)(即新建的文件,沒有add的文件)是無法用
git checkout -- file
來撤銷的;對于這些文件需要手動rm
- 暫存區(qū)內(nèi)容撤銷
- 暫存區(qū)就是說已經(jīng)add,還未commit的文件;
- git reset HEAD [file] : 撤銷暫存區(qū)修改,此時即將上次add到暫存區(qū)的內(nèi)容(還未commit)重新回退到工作區(qū);實際上是版本回退的一個變種使用
- 版本回退
- 當已經(jīng)將修改commit到分支上時,如果要回退,只能回退版本了
- git reset --hard commit_id : 將暫存區(qū)的內(nèi)容回滾到commit_id的提交,同時這里加了--hard參數(shù),表示回滾工作去為commit_id內(nèi)容;需要注意的是,如果此時工作區(qū)有未追蹤的內(nèi)容,那么其將丟失(簡單來說這條命令會同時回滾暫存區(qū)和工作區(qū))
- git reset --soft commit_id : 加上--soft指令后,暫存區(qū)和工作區(qū)的內(nèi)容都不會改變,只是單純的混滾分支和HEAD到commit_id
- git reset commit_id : 如果沒有加參數(shù)(實際上是有參數(shù)的,默認參數(shù)為--mixed),此時會將暫存區(qū)內(nèi)容回滾,但是工作區(qū)不受影響
-
可以結合下圖來理解和記憶
- 關于回退的幾點建議
- 回退之前考慮清清楚,對于Untracked文件的某些回退操作是無法恢復的
- 弄清楚命令的作用效果再使用,特別是在共享分支上的操作
diff操作
- 之所以將這個命令單獨提出來,是因為這個命令是很有用的
- git diff : 比較工作區(qū)和暫存區(qū)的區(qū)別(也可以比較特定的文件: git diff file (仍然是工作區(qū)和暫存區(qū)中file內(nèi)容的比較))
- git diff --cached : 比較的是暫存區(qū)和版本庫最后一個版本的區(qū)別
- git diff HEAD : 比較的是工作目錄樹(包括暫存區(qū)和工作區(qū))和版本庫最后一個版本的區(qū)別
- git diff commit_id -- file : 具體文件的比較(沒有加具體文件時比較的所有)比較版本號為commit_id的file文件和當前工作區(qū)的file文件的內(nèi)容區(qū)別
分支操作
- 分支在我們?nèi)粘i_發(fā)中是很重要的概念,特別是當項目變得很大,版本迭代很快時,管理好分支顯得尤為重要
- 區(qū)分本地分支和遠程分支
- 遠程分支: 遠程倉庫中的分支;所謂的遠程分支就是從本地推送到遠程倉庫時指定的如:
git push origin master
(創(chuàng)建遠程分支master,并將當前分支內(nèi)容推送到遠程master分支)或者git push origin dev
(創(chuàng)建遠程分支dev,并將當前分支內(nèi)容推送到遠程dev分支)(注意: 可以指定推送到那個分支,如果沒有該遠程分支,將創(chuàng)建該遠程分支)- 本地分支:
- git ls-remote : 列出遠程分支
- git branch : 不帶參數(shù)時,只是列出本地分支
- git branch --all : 列出所有分支,包括遠程分支
- Clone倉庫后的分支
多人合作開發(fā)時,一般會有master,dev等幾種主干和長期分支(關于這些稍后講解);當我們剛開始上手一個項目時,往往都不是從一個新項目開始,當Clone下代碼庫之后,會默認創(chuàng)建一個本地master分支,與遠程的master分支同步,如下
- 但是實際上我們需要在dev分支上進行開發(fā),而且dev分支往往也是最新的;因此此時我們需要切換到dev分支,使用命令
git checkout dev
,該命令可以遠程的dev分支在本地變得可追蹤(track),與之具有相同效果的命令還有git checkout --track origin/dev
- 之后,我們可以在dev分支上再創(chuàng)建自己的個人分支開發(fā),每完成一個部分之后merge到dev并推送到遠程(git push origin dev)
- 上面是我們接手一個項目時的大致流程,但是實際上其中還有很多比較坑的地方,比如說沖突...
- 推送到遠程的時候先diff一下,再次確認提交的文件;
沖突處理
- 沖突:
- 沖突的出現(xiàn)一般是在不同分支上修改了同一個文件,不同的分支可以是本地的不同分支,也可以是不同客戶端的分支
- 解決沖突的一般是更新代碼后手動解決之后再提交
- 常見場景是,如上在dev分支上開發(fā)時,當需要推送到遠程時,如果遠程的dev分支比本地dev分支新,那么推送就會失敗;所以一般情況下,推送到遠程之前,先pull更新一下代碼,如果有沖突手動解決之后再提交即可(也可以使用fetch)(關于二者的區(qū)別,參見博客)
gitignore文件的編寫
- 編寫規(guī)范
- 所有空行或者以 # 開頭的行都會被 Git 忽略
- 可以使用標準的 glob 模式匹配
- 匹配模式可以以(/)開頭防止遞歸
- 匹配模式可以以(/)結尾指定目錄
- 要忽略指定模式以外的文件或目錄捅彻,可以在模式前加上驚嘆號(!)取反
示例如下:
# 忽略所有的.a文件
*.a
# 但是不能忽略lib.a,即使上面使用了.a來忽略所有.a文件
!lib.a
# 只是忽略當前目錄下TODO文件,而不忽略類似subdir/TODO
/TODO
# 忽略所有在build/中的文件
build/
# 忽略doc/notes.txt之類文件,但是不忽略如doc/server/arch.txt之類的文件
doc/*.txt
# 忽略在doc/目錄下所有的.pdf文件,包括doc子目錄下的.pdf文件也會被忽略
doc/**/*.pdf
三. Git常見分支模型:GitFlow
-
先賦一張經(jīng)典的圖
- 該分支模型是常見也是用的最多的一種,不難理解;但是并不是每一個部分都是必須的,可以根據(jù)實際需要選擇
- master: 只用于發(fā)布新版本
- develop: 開發(fā)主分支,每個人可以有自己的分支
- hotfix: bug修復,短期存在,merge到dev和master
- feature: 新特性開發(fā)分支,短期存在,merge到dev
四. 其他
只是想分享一些其他的東西 :)
- shell腳本
- 補丁: 使用場景之一是,當你發(fā)現(xiàn)項目中有bug,但是你沒有修改權限時,此時可以使用文件補丁的形式發(fā)給leader,顯得專業(yè)一些