Git詳細介紹
Git
1. 學習目標
2. 版本控制
版本控制是一種記錄若干檔案內容變化,以便將來查閱特定版本修訂情況的系統. 簡單講就是備份和記錄. 接下來我們要了解三種不同版本控制的發展歷程.。
2.1. 本地版本控制系統
人們把專案拷貝到本地磁碟上進行備份, 然後以命名方式來區分. 這種做法好處是簡單, 但壞處也不少比如備份比較多或許就會混淆不同版本之間的區別. 那為了解決這個問題, 有人就開發了一個本地版本的管理系統, 它的結構圖如下:
本地版本管理就是把版本號存入資料庫來記錄檔案的歷次更新差異。
2.2. 集中化版本控制系統
本地版本控制系統能夠將不同版本的文件儲存下來並且藉助版本記錄可以很方便定位相關檔案但又引入了新的問題,如何讓在不同系統上的開發者協同工作?於是,集中化的版本控制系統( Centralized Version Control Systems,簡稱 CVCS )應運而生。這類系統,諸如 CVS,Subversion 以及 Perforce 等,都有一個單一的集中管理的伺服器,儲存所有檔案的修訂版本,而協同工作的人們都通過客戶端連到這臺伺服器,取出最新的檔案或者提交更新。多年以來,這已成為版本控制系統的標準做法 。
這樣做的好處是解決了人們開發協同的問題, 但是把所有的程式碼提交到同一臺伺服器上有一個很明顯的問題就是單點故障, 如果這臺伺服器當機了, 那所有人都不能提交程式碼, 還有如果這臺伺服器如果磁碟發生故障,碰巧沒做備份,或者備份不夠及時,就還是會有丟失資料的風險。最壞的情況是徹底丟失整個專案的所有歷史更改記錄,而被客戶端提取出來的某些快照資料除外,但這樣的話依然是個問題,你不能保證所有的資料都已經有人事先完整提取出來過。本地版本控制系統也存在類似問題,只要整個專案的歷史記錄被儲存在單一位置,就有丟失所有歷史更新記錄的風險。
2.3. 分散式版本控制系統
為了解決集中化版本管理所帶來的問題分散式版本管理控制系統(Distributed Version Control System,簡稱 DVCS)就應運而生了. 在這類系統中,像 Git,Mercurial,Bazaar 以及 Darcs 等, 客戶端不只是提取出最新版的檔案快照, 而是把最原始的程式碼倉庫映象到本地. 這樣一來,任何一處協同工作用的伺服器發生故障,事後都可以用任何一個映象出來的本地倉庫恢復。因為每一次的提取操作,實際上都是一次對程式碼倉庫的完整備份。
所以綜上來看的集中化版本控制系統是對本地版本控制系統的一次升級, 因為它加入了協同操作, 分散式版本控制系統是對集中化控制系統的一次補充, 使之更加完善。
3. Windows上安裝Git
最早Git是在Linux上開發的,很長一段時間內,Git也只能在Linux和Unix系統上跑。不過,慢慢地有人把它移植到了Windows上。現在,Git可以在Linux、Unix、Mac和Windows這幾大平臺上正常執行了。
在Windows上使用Git,先從Git官網直接下載安裝程式,選擇指定系統下載,然後按預設選項安裝即可。安裝完成後,在開始選單裡找到“Git”->“Git Bash”,顯示出類似命令列的視窗,說明Git安裝成功!
在視窗內輸入 git --version 檢視git 版本資訊如下:
在使用用Git工作之前,我們需要做個一次性的配置。方便後續Git能跟蹤到誰做了修改,我們需要設定對應的使用者名稱與郵箱地址。
git config --global user.name "your_username"
git config --global user.email your_email@domain.com
git config --list 檢視所有配置
注意 git config 命令的 --global 引數,用了這個引數,表示你這臺機器上所有的Git倉庫都會使用這個配置,當然也可以對某個倉庫指定不同的使用者名稱和Email地址。
4. 理解Git檔案的三種狀態與工作模式
使用Git 操作檔案時,檔案的狀態有以下三種:
狀態 | 描述 |
---|---|
已提交(committed) | 已提交表示資料已經安全的儲存在本地資料庫中。 |
已修改(modified) | 已修改表示修改了檔案,但還沒儲存到資料庫中。 |
已暫存(staged) | 已暫存表示對一個已修改檔案的當前版本做了標記,使之包含在下次提交的快照中。 |
針對Git 檔案的三種狀態,這裡需要了解Git專案的三個工作區域:工作區、暫存區和Git倉庫。
分類 | 描述 |
---|---|
工作區 | 簡單的理解為在電腦裡能看到的目錄,比如自己建立的本地專案目錄 |
暫存區 | Git的版本庫裡存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git自動建立的第一個分支master,以及指向master的一個指標叫HEAD。 |
Git倉庫 | 工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。 |
基本的Git 工作流程描述如下:
- 在工作區中修改某些檔案。
- 對修改後的檔案進行快照,然後新增到暫存區。
- 提交更新,將儲存在暫存區域的檔案快照永久轉儲到 Git 倉庫中。
流程圖如下:
5. 建立版本庫並提交檔案
版本庫又名倉庫,可以簡單理解成一個目錄,這個目錄裡面的所有檔案都可以被Git管理起來,每個檔案的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”。理解了Git 檔案狀態與三種工作區域之後,通過一個例子來體驗Git對於檔案的基本操作。
編寫一個文字檔案並將檔案提交到git倉庫
- 初始化git 本地倉庫
通過執行 git init 命令在本地初始化一個本地倉庫,執行該命令後會在本地初始化一個沒有任
何檔案的空倉庫。
- 新建文字檔案 git01.txt 並新增到暫存區
文字內容如下:
git status 命令用於顯示工作目錄和暫存區的狀態。使用此命令能看到那些修改被暫存到了, 哪些沒有, 哪些檔案沒有被Git tracked到。
執行 git add 命令新增檔案到暫存區
git add path 通常是通過git add <path>的形式把<path>新增到索引庫中,<path>可以是檔案也可以是目錄。
git不僅能判斷出<path>中,修改(不包括已刪除)的檔案,還能判斷出新添的檔案,並把它們的資訊新增到索引庫中。
此時可以看到有一個git 已tracked 到新檔案git01.txt,檔案被成功存放到暫存區
- 提交檔案到本地版本庫
檔案被新增到暫存區後,執行 git commit 命令提交暫存區檔案到本地版本庫中。
git commit 命令用於將更改記錄(提交)到儲存庫。將索引的當前內容與描述更改的使用者和日誌訊息一起儲存在新的提交中。通常在執行提交時 在 git commit 命令後跟上 -m 屬性 加入本次提交的記錄說明 方便後續檢視提交或改動記錄。
git log
:命令用於顯示提交日誌資訊。 (比較常用,後續講到時光穿梭時會經常使用該命令)。
6. 時光穿梭機
企業中在多人的專案開發環境下,使用Git 版本控制工具對專案版本進行管理時,通常會對專案不同版本的檔案進行檢視,專案歷史版本,未來版本的切換操作,對於一個專案開發人員,此時對於Git 的這些基本命令操作就成為了一項基本技能。
6.1. 修改檔案與檔案提交
修改後內容如下:
此時當檔案修改後 使用 git status 命令可以看到git 檢測到檔案被修改,git 版本庫給出的下一步操作是新增修改的檔案到暫存區 此時執行新增操作命令
執行提交
git log 命令檢視操作日誌記錄
修改需要注意的問題
下面再次修改git01.txt 然後執行提交操作
執行提交操作
此時 執行 git diff HEAD – git01.txt 與版本庫內容進行比較結果如下:
差異比較說明
`---`:表示變動前的檔案
`+++`:表示變動後的檔案
變動的位置用兩個@作為起首和結束
@@ -1,2 +1,3 @@:減號表示第一個檔案,"1"表示第1行,"2"表示連續2行。同樣的,"+1,3"表示變動後,成為第二個檔案從第1行開始的連續3行。
可以看出:文字中第三行內容並沒有提交到版本庫中 原因在於修改後的git01.txt 並沒有新增到暫存區,所有執行提交操作並不會發生改變。
暫存區檔案提交與撤銷
當發現因失誤而將檔案新增到暫存區時,git 支援檔案的撤銷操作 執行命令 git reset HEAD 檔案
操作如下:
檢視版本庫狀態並執行撤銷操作
再次檢視版本庫狀態 test.txt 成為未追蹤檔案
6.2. 版本回退
當檔案修改後被提交的次數很多時,對於版本庫中存放的檔案就會出現不同的版本,在多人開發的專案環境中,通常會對不同版本檔案進行檢視甚至回退的情況(比如某些遊戲中所提供的狀態儲存功能,能夠在某一時刻儲存整個遊戲場景狀態以方便後續繼續在該狀態下進行遊戲進行而不是從頭開始),值得慶幸的是 Git 也提供了同樣的功能,能夠讓開發者在不同版本的專案中進行切換,達到時空穿梭自如的目的!
對於上面操作的git01.txt 檔案已有幾個版本,對於歷史版本的檢視 使用 git log 命令:
git log:命令用於顯示提交日誌資訊
列表顯示的結果按提交時間倒敘排序,其中第一條中 HEAD -> master 代表當前指標指向Git 版本庫中master 主幹分支,每次提交 Git 內部均會生成一個唯一的SHA 演算法構建的字串來唯一標識當前版本此時如果想要執行版本版本回退操作使用命令 git reset
git reset 命令用於將當前HEAD復位到指定狀態。一般用於撤消之前的一些操作(如:git add,git commit等)。
回滾前在執行兩次提交操作 方便檔案不同版本間的切換
第三次提交 修改後的git01.txt 內容如下:
第四次提交 修改後的git01.txt 內容如下:
git log 檢視提交歷史記錄如下
當然,如果提交歷史記錄較多 可以加入數字控制顯示的版本記錄數 並且使用 --pretty=oneline 簡化輸出如下:
顯示最近三次提交
切換版本前 git01.txt 內容如下:
回退到上一版本
執行 git reset --hard HEAD^
HEAD^:將指標指向上一個版本,如果是上上一個就是 HEAD^^,上上上一個HEAD^^^,但這樣記就比較麻煩,如果回退版本較多,簡寫為 HEAD~100 往前回退100個版本 ~後跟數字即可
檢視回退後的git01.txt內容如下:
回退操作已經完成,但此時如果想要回到未來的版本即最新的版本怎麼辦呢? 其實這裡也比較簡單,前面說到針對提交後的版本庫,每個版本均會有一個唯一標識,這裡找到對應版本標識即可完成回到未來版本的操作如下
執行git reset 命令如下:
如果此時回到某一個版本後直接關閉了當前git 命令視窗 怎麼樣才能回到未來版本呢?因為此時未來版本的唯一標識id 在視窗中看不到了!
值得慶幸的是,Git早已為你想到了這種情況,Git提供了一個命令 git reflog 用來記錄使用者操作的每一次命令,效果如下:
git reflog:檢視記錄在本地的HEAD和分支引用在過去指向的位置。
6.3. 檔案刪除
在Git中,刪除檔案同樣是一個修改操作,即在Git世界中,Git僅僅關注檔案是否被修改(檔案新增,更新,刪除)
在工作區新增新檔案git02.txt 內容如下:
將檔案新增到版本庫
檔案提交到版本庫後,在工作目錄執行手動刪除操作後執行 git status 命令可以看到Git 能夠追蹤到檔案被刪除情況,注意此時版本庫中檔案並沒有被刪除,只是工作目錄中檔案被刪除!
如果此時發現檔案是被誤刪除呢,不用擔心,這裡可以將誤刪除的檔案重新從版本庫中檢出,執行命令:
git checkout -- 檔名
如果確定是要執行刪除操作 執行git rm 命令即可
7. 遠端倉庫
Git是一個分散式版本控制系統,同一個Git倉庫,可以分佈到不同的機器上。截止目前,並沒有看到分散式的環境,因為以上的操作都在在本地發生的,對於Git,除了前面提到的本地版本庫外,Git 支援遠端倉庫的託管服務即使用者可以將本地版本庫中的檔案託管到遠端伺服器進行儲存,這樣就極大的方便開發,無論你走到哪,只要你的機器能夠聯網,就可以通過遠端的倉庫地址得到一份相同的專案庫檔案,並且下載到本地的檔案版本記錄與遠端檔案版本保持一致,並且可以很方便的實現多人協同開發操作。
對於Git 遠端倉庫,GitHub( https://github.com/ )是比較知名的一個,目前已被微軟收購,而國內比較知名的當屬碼雲( https://gitee.com/ )了,當然除了這些遠端倉庫外,在公司,有的公司處於安全考慮,可能會自己搭建一套Git服務區來自Git的遠端倉庫,對於內部倉庫會有專門人員來進行維護操作。這裡以當下比較流行的GitHub倉庫來介紹Git 遠端倉庫基本操作與使用。
7.1. 克隆遠端專案到本地
初次接觸GitHub的話,在沒有賬號的情況下,也可以很容易得到一些比較好的開源專案,即通過克隆的方式將遠端專案下載到本地 比如現在java12 都已經發布,想要找一些java12 相關的專案入門,這裡就可以藉助GitHub來發現你想要的相關專案
克隆專案到本地執行 git clone 命令
在本地磁碟指定目錄下右鍵 git bash here 操作
此時在本地就得到了遠端的相關專案.
7.2. 將本地庫推送到遠端
- 建立本地版本庫並提交檔案到本地庫(這裡以前面建立版本庫為主,這裡不再贅述)
- 使用GitHub建立遠端庫git01 如下
- 推送本地Git版本庫檔案到遠端倉庫git01
推送本地庫檔案到遠端有兩種方式 - 使用Https
- 使用SSH
使用Https 比較簡單,使用SSH 加密方式是Git 建議的一種推送,時間上與響應上效率都更高,這裡介紹SSH推送方式配置
- 使用本地Git客戶端生成SSH公鑰與私鑰 執行命令 ssh-keygen -t rsa -C “GitHub賬戶郵
箱”
- GitHub 公鑰配置
設定公鑰標題與公鑰串內容
- 檢查測試連結 執行命令 ssh -T git@github.com
- 使用SSH執行遠端推送操作
根據GitHub 說明 執行SSH 推送 首先繫結遠端地址到本地執行命令
git remote add origin git@github.com:zsyue/git01.git
執行遠端推送操作 將本地庫推送到遠端master 主分支 執行命令
git push -u origin master
檢視遠端倉庫 到此,使用SSH推送本地版本庫檔案到GitHub遠端庫操作成功完成!
8. Git 分支操作
開發企業專案中在使用Git 或者其他類似版本控制軟體對專案版本進行管理時,多人合作的專案在開發時通常不會直接在主幹master 上進行操作,而是重新開闢新的分支,在新的分支上進行開發 除錯 等操作,當專案除錯通過時才會將分支專案的程式碼合併到主幹中,這是在實戰中比較好的一種策略,特別是多人協同開發一個專案的情況下尤其明顯。Git 對於分支操作提供了一下基本命令:
命令 | 描述 |
---|---|
git checkout branch | 切換到指定分支 |
git checkout -b new_branch | 新建分支並切換到新建分支 |
git branch -d branch | 刪除指定分支 |
git branch | 檢視所有分支, 並且*號標記當前所在分支 |
git merge branch | 合併分支 |
git branch -m 或 -M oldbranch newbranch | 重新命名分支,如果newbranch名字分支已經存在,則需要使用-M強制重新命名,否則,使用-m進行重新命名。 |
8.1. 本地分支建立、合併、重新命名與刪除
以前面git版本庫為例。
- 建立本地分支、並檢視分支
預設Git 版本庫所在分支為master 通常稱為專案的主幹,開發中通常會在主幹上建立新的分支類進行本地開發工作 使用命令 git checkout -b new_branch 建立分支
分支建立完畢 該命令會自動切換到新建分支上 如上圖
使用命令 git branch 檢視分支列表 * 號標記為當前git 所在分支
- 分支上新增檔案leaf01.txt 新增操作同主幹新增命令 leaf01.txt 檔案內容如下:
- 切換到主幹master 並執行合併操作
- 重新命名分支leaf01->leaf02
- 刪除分支(不能再待刪除的分支上執行刪除當前分支操作!!!)
8.2. 分支Push與Pull操作
相關命令操作
命令 | 描述 |
---|---|
git branch -a | 檢視本地與遠端分支 |
git push origin branch_name | 推送本地分支到遠端 |
git push origin :remote_branch | 刪除遠端分支(本地分支還在保留) |
git checkout -b local_branch origin/remote_branch | 拉取遠端指定分支並在本地建立分支 |
- 檢視遠端倉庫 此時遠端倉庫只有主幹master
- 檢視遠端倉庫 此時遠端倉庫只有主幹master
遠端檢視 此時本地分支遠端推送完成(注:推送遠端分支名稱可改)。
- 遠端建立dev分支並拉取分支到本地
GitHub支援遠端分支線上建立,這裡dev開發分支建立後分支檔案內容與主幹master一致
本地執行克隆 並拉取dev 分支到本地
執行 git clone 命令
檢視本地專案並執行命令 git checkout -b dev origin/dev 拉取dev 開發分支
8.3. 分支操作衝突出現與解決
開發中對不同分支下同一檔案進行修改後執行合併時就會出現檔案修改衝突情況,這裡說明一種比較常見的衝突問題 以master 和leaf01 兩個分支進行演示說明。
8.3.1. 本地分支操作衝突
- 修改master與leaf01分支前git01.txt 檔案內容狀態
master 主幹檔案內容:
leaf01 分支檔案內容:
- 分支leaf01 下修改給git01.txt 並執行提交操作 效果如下
- 主幹master 下修改git01.txt 並執行提交操作
- 執行合併操作 此時發現git 在合併中產生衝突
執行 cat git01.txt 可以看出衝突檔案內容
Git用<<<<<<<,=======,>>>>>>>標記出不同分支的內容
<<<<<<< HEAD 當前git 指向分支 這裡指的為master
======= 分離不同分支修改的內容
>>>>>>> leaf01 leaf01 與 master 在git01.txt 同一行同時出現了修改操作 這裡git 是不允許發生的
此時出現衝突後 這裡對git01.txt 內容進行修改 (實際開發視情況而定 這裡將內容合併為一行)
修改完畢master下執行提交即可 執行命令檢視分支合併圖 git log --graph --pretty=oneline
8.3.2. 多人協同操作衝突
拉取遠端庫dev 並在本地建立dev開發庫,執行命令 git checkout -b dev origin/dev 這裡以同
臺機器不同視窗來模擬兩個使用者操作同一分支同一檔案(實際開發時多人操作統一檔案衝突情況比較常見)
這裡兩個客戶端以c1與c2來描述
c1 客戶端本地修改dev 分支git01.txt 檔案並在本地執行提交操作 效果如下
執行遠端推送 將本地C1客戶端提交的git01.txt 推送到遠端dev分支
而此時C2 客戶端在本地同樣修改了dev分支git01.txt 檔案並在本地執行提交
執行推送操作 此時衝突出現 原因是另外一個使用者推送的檔案與當前客戶端推送內容存在衝突:
此時解決方式Git 已有對應提示 Push 之前先執行Pull 操作 將遠端檔案拉取到本地 解決完衝突後再次執行Push 操作
衝突解決
先執行Pull 拉取操作
檢視衝突檔案內容
這裡在本地先處理衝突 將文字進行合併 然後提交 在 push 操作即可
遠端倉庫內容如下:
相關文章
- Git學習1 --- 版本控制工具詳細介紹Git
- javascript this詳細介紹JavaScript
- JDBC 詳細介紹JDBC
- Kafka詳細介紹Kafka
- Go Channel 詳細介紹Go
- Nacos 介面詳細介紹
- MQ詳細命令介紹MQ
- Recovery命令詳細介紹
- Vmstat 命令詳細介紹
- Flutter系列(一)——詳細介紹Flutter
- Nginx服務詳細介紹Nginx
- python字典詳細介紹Python
- Spring bean詳細介紹SpringBean
- Http Module 的詳細介紹HTTP
- Java異常詳細介紹Java
- 【SCN】Oracle SCN 詳細介紹Oracle
- SOLIDWORKS API詳細介紹SolidAPI
- Webpack 打包 Javascript 詳細介紹WebJavaScript
- mysql binlog詳細介紹MySql
- java泛型詳細介紹Java泛型
- 【工具】Sublime使用詳細介紹
- asmcmd工具的詳細介紹ASM
- json詳細介紹(for Java)JSONJava
- Mysqldump工具的詳細介紹MySql
- rman超詳細命令介紹
- Aix 上NFS詳細介紹AINFS
- ApplicationContext 詳細介紹APPContext
- TreeViewTemplate移動元件詳細介紹View元件
- pyhanlp 文字聚類詳細介紹HanLP聚類
- LVM詳細介紹及建立LVM
- oracle 大頁配置詳細介紹Oracle
- js中typeof用法詳細介紹JS
- 詳細介紹Linux指令odLinux
- Linux下udev詳細介紹Linuxdev
- MongoDB備份方式詳細介紹MongoDB
- Oracle觸發器詳細介紹Oracle觸發器
- Apache (http server)的詳細介紹ApacheHTTPServer
- Dart語言詳解(一)——詳細介紹Dart