1. 程式人生 > 其它 >Git操作小技巧

Git操作小技巧

一.Git概念
​​Git(讀音為/gɪt/)是一個​開源的分散式版本控制系統​,可以有效、高速地處理從很小到非常大的專案版本管理。 [1] 也是Linus Torvalds為了幫助管理Linux核心開發而開發的一個開放原始碼的版本控制軟體。​​

​二.Git結構理解​


上圖展示了git的整體架構,以及和各部分相關的主要命令。先說明下其中涉及的各部分。

​工作區(working directory),​簡言之就是你工作的區域。對於git而言,就是的本地工作目錄。工作區的內容會包含提交到暫存區和版本庫(當前提交點)的內容,同時也包含自己的修改內容。

​暫存區(stage area, 又稱為索引區index)​,是git中一個非常重要的概念。是我們把修改提交版本庫前的一個過渡階段。檢視GIT自帶幫助手冊的時候,通常以index來表示暫存區。在工作目錄下有一個.git的目錄,裡面有個index檔案,儲存著關於暫存區的內容。git add命令將工作區內容新增到暫存區。

​本地倉庫(local repository)​,版本控制系統的倉庫,存在於本地。當執行git commit命令後,會將暫存區內容提交到倉庫之中。在工作區下面有.git的目錄,這個目錄下的內容不屬於工作區,裡面便是倉庫的資料資訊,暫存區相關內容也在其中。這裡也可以使用merge或rebase將遠端倉庫副本合併到本地倉庫。圖中的只有merge,注意這裡也可以使用rebase。

遠端版本庫(remote repository),與本地倉庫概念基本一致,不同之處在於一個存在遠端,可用於遠端協作,一個卻是存在於本地。通過push/pull可實現本地與遠端的互動;

​遠端倉庫副本​,可以理解為存在於本地的遠端倉庫快取。如需更新,可通過git fetch/pull命令獲取遠端倉庫內容。使用fech獲取時,並未合併到本地倉庫,此時可使用git merge實現遠端倉庫副本與本地倉庫的合併。git pull 根據配置的不同,可為git fetch + git merge 或 git fetch + git rebase。rebase和merge的區別可以自己去網上找些資料瞭解下。

看到這裡,不僅清楚了 git fetch 與 git pull。而且我們使用每個命令時,也能清楚的明白此時git做了什麼工作。

臨時儲存區,git stash

​(參考連結:https://blog.csdn.net/mozes1/article/details/106387189/)​

三.如何優雅的提交程式碼?
1.臨時儲存區流
a.將工作區的修改儲存到臨時儲存區,保證工作區的status狀態是一個乾淨的狀態

b.進行遠端倉庫和本地倉庫程式碼的同步

c.將臨時儲存區中的程式碼彈出到工作區,這樣會自動合併工作區中的檔案,有可能有衝突,有可能沒有衝突。

d.有衝突就解決衝突然後正常提交程式碼即可

2.本地倉庫流
a.正常開發程式碼,寫好了就提交到自己的本地倉庫

b.感覺程式碼寫好了,想推送到遠端倉庫,那麼這個時候需要遠端倉庫和本地倉庫程式碼的同步。

c.這裡可以看到同步程式碼,出現了衝突,並且上面也提示了衝突解決後應該繼續執行git rebase --continue

d.衝突解決,正常往遠端倉庫推送程式碼即可

3.總結:
自己喜歡哪個就選哪個,儘量保證遠端倉庫和本地倉庫同步程式碼的時候,工作區是乾淨的。因為有的同學喜歡用git pull來同步程式碼,其實git pull = git fetch + git merge的。這樣會導致同步程式碼後直接合並工作區,有的時候合併會導致一些意外的麻煩。

四.如何優雅的合併分支?
1.在dev分支中增加branch.txt

2.分支切換到master,在master分支增加內容

3.將分支切換回dev分支,將master分支合併到dev分支,將master分支合併到dev分支

4.出現衝突將衝突解決,並提交程式碼,推送到遠端的dev分支

5.此時將分支切回master分支,將dev分支合併到master分支。

總結:可以看到成功合併到master分支,並且推送到遠端分支。

為什麼要先將master分支合併到dev分支呢?
這樣坐是為了將衝突在dev分支解決,然後再將dev分支程式碼合併到master,這樣可以最小限度汙染master分支程式碼。

git merge --no-ff:禁止快進式合併

Git 合併兩個分支時,如果順著一個分支走下去可以到達另一個分支的話,那麼 Git 在合併兩者時,只會簡單地把指標右移,叫做“快進”(fast-forward),比如下圖:

要把 feature 合併到 master 中,執行以下命令

$ git checkout master
$ git merge feature

結果就會變成

因為 feature 就在 master 的下游,所以直接移動了 master 的指標,master 和 feature 都指向了 C。而如果執行了​​git merge --no-ff feature​​的話,是下面的結果:


由於​​--no-ff​​禁止了快進,所以會生成一個新的提交,master 指向 G。

從合併後的程式碼來看,結果其實是一樣的,區別就在於​​--no-ff​​會讓 Git
生成一個新的提交物件。為什麼要這樣?通常我們把 master 作為主分支,上面存放的都是比較穩定的程式碼,提交頻率也很低,而 feature
是用來開發特性的,上面會存在許多零碎的提交,快進式合併會把 feature 的提交歷史混入到 master 中,攪亂 master
的提交歷史。所以如果你根本不在意提交歷史,也不愛管 master 乾不乾淨,那麼​​--no-ff​​其實沒什麼用。不過,如果某一次 master 出現了問題,你需要回退到上個版本的時候,比如上例,你就會發現退一個版本到了 B,而不是想要的 F,因為 feature 的歷史合併進了 master 裡。

​​--no-ff​​在這的作用是禁止快進式合併。

(參考:​​https://blog.csdn.net/zombres/article/details/82179122​​)

五.其它
1.reset命令
git reset --hard [索引] : 本地庫索引移動的同時,重置暫存區,重置工作區

git reset --mixed [索引] :本地庫索引移動的同時,重置暫存區,工作區不動

git reset --soft [索引]:本地庫索引移動的同時,暫存區,工作區都不動

回退到上一個版本:git reset --hard HEAD^

回退到上上一個版本:git reset --hard HEAD^^

2.找回暫存區刪除的檔案
a.刪除工作區資料

b.同步到暫存區

c.後悔了,恢復暫存區中資料

或者:

3.找回本地庫刪除的檔案
a.新建一個檔案test.txt

b.將它add到暫存區中

c.通過commit提交到本地倉庫

d.刪除工作區中的test.txt

e.將刪除同步到暫存區

f.將刪除同步到本地倉庫

g.檢視日誌,將歷史版本切回剛才新增檔案的那個版本