Git的使用與五大場景的運用



Git是版本管理工具的一種,是分布式的控制系統。之前用過SVN,它是中心版本控制系統,與Git有很大的不同,當今主流的版本控制都是用的Git,所以希望借此課程的機會,了解一下Git的使用。

一、Git的基礎

1、Git的基本運作流程

(1) workspace->index->Repository

​ 在本地寫的代碼都在workspace中,通過add指令暫存到index中,然后通過commit提交到本地倉庫Repository中。如果有多位項目成員,則每個成員都對應一套本地倉庫管理系統,各自寫的代碼互不干擾。這也就是分布式的體現,成員之間並行進行,互不干擾。

(2) checkout

​ 可以切換Repository中的某個分支。這是版本控制的重要功能,在不同分支上工作。

(3) pull, push, fetch/clone

​ 這是遠端Remote與本地之間的數據同步操作。

2、Git與SVN的不同

SVN工作圖

​ 可見SVN並沒有本地的倉庫,只有一個集中的服務器,所有同步操作直接與服務器進行,這意味着必須要聯網才能查看歷史版本信息,進行版本控制,而Git擁有本地倉庫,本地即有全部的版本歷史信息,如果沒有網絡,只需提交到本地倉庫,之后再與Remote同步即可。

​ svn這種集中式十分依賴於中心服務器,缺點不言而喻。Git分布式有去中心化的特點,每個使用者都是平等的,每人都有一套完整的版本庫,並且每個人的又有各自修改后寫入的新代碼。使用者之間可以比較交換,同步。SVN和Git的關系類似於C/S和P2P。

二、Git的操作與使用

1、Git的基本配置

Github, Gitee等雲平台都是基於Git的,它擔任一個托管代碼的服務器的角色,但它與SVN中的服務器還是不一樣,因為它們與各個主機之間的關系是平等的。

無論是使用Github還是Gitee都需要本地有個Git工具,當與雲端服務器同步時,都需要Git與它們通信。

(1) 安裝Git

  • 先下載安裝Git: https://git-scm.com/download;

  • 配置用戶名郵箱:

    git config --global user.name "your_name"

    git config --global user.email "your_email"

  • 生成SSH Key:

    ssh-keygen -t rsa -C your_email

  • 查看Key:

    open ~/.ssh

    將查到的Key復制下來,這就是公鑰,之后會用來配置GitHub/Gitee

(2) 配置GitHub

配置界面

在GitHub->settings->SSH keys中,如圖,粘貼進之前查看到的Key即可。此時Git便可以與Github通信,每次同步Github時不需要再登陸。

2、Git的基本操作

  1. git init - - 初始化代碼倉庫

  2. git clone - - 克隆遠程倉庫
    PS:如果希望在克隆的時候,自己定義要新建的項目目錄名稱,可以在上面的命令末尾指定新的名字:

    $ git clone git://github.com/schacon/grit.git mygrit

  3. git add - - 把需要提交的所有修改放到暫存區(Stage)

    • git add file – 提交指定文件
    • git add . || git add -A – 提交所有文件
    • git add *.js – 提交所有.js格式文件
    • git add -f file – 強制添加
  4. git diff - - 查看當前目錄的所有修改(#當暫存區中沒有文件時,git diff比較的是,工作區中的文件與上次提交到版本庫中的文件。
    #當暫存區中有文件時,git diff則比較的是,當前工作區中的文件與暫存區中的文)

    • git diff HEAD - - file – 比較工作區中的文件與版本庫中文件的差異。HEAD指向的是版本庫中的當前版本,而file指的是當前工作區中的文件。
  5. git commit -m “message” - - 提交代碼

  6. git rm - - 會把文件從當前目錄刪除(不會保存刪除的文件)。如果需要從Git倉庫中刪除,但保留在當前工作目錄中,亦即從跟蹤清單中刪除,可以使用git rm -r --cached readme.md
    PS:如果一個文件已經被提交到版本庫,那么你永遠不用擔心誤刪,但是要小心,你只能恢復文件到最新版本,你會丟失最近一次提交后你修改的內容。

  7. git log - - 查看歷史記錄,git log命令顯示從最近到最遠的提交日志

    • git log --graph – 查看分支合並圖
  8. git reflog - - 用來記錄你的每一次命令

  9. git remote - - 查看當前的遠程庫

  10. git remote -v - - 可以顯示對應的克隆地址(對於多個遠程倉庫很有用)

  11. git remote add [short_name] - - 可以添加新的遠程倉庫

  12. git remote add origin < address > - - 關聯一個遠程庫

  13. git fetch [remote-name] - - 可以從遠程倉庫抓取數據到本地。

  14. git pull - - 更新數據

  15. git push [remote_name] [branch_name] - - 推送數據到遠程倉庫 默認使用origin和master

  16. git push -u origin master [-f] - - 第一次將本地庫的所有內容推送到遠程庫上

  17. git remote show origin - - 查看遠程倉庫信息

  18. git remote rename [old_name] - - 遠程倉庫重命名

  19. git remote rm [remote_name] - - 刪除遠程倉庫

  20. git branch -d < name > - - 刪除本地分支

  21. git tag - - 顯示當前庫中的標簽

  22. git branch - - 可顯示當前所有分支。可以使用–merged和–no-merged查看已經合並、未合並的分支。

  23. git branch <branch_name> - - 創建新分支

  24. git branch -r - - 查看遠程倉庫分支

  25. git checkout <branch_name> - - 切換到指定的分支

  26. git checkout -b <branch_name> - - 創建新分支並切換到該分支

  27. git merge 合並分支
    舉例:
    將hotfix分支合並到master上需要:
    git checkout master
    git merge hotfix
    合並之后可以使用git branch -d hotfix刪除分支。
    如果合並時存在沖突,需要手工修改
    合並分支時,加上—no-ff參數就可以用普通模式合並,合並后的歷史有分支,能看出來曾經做過合並,而fast forward合並就看不出來曾經做過合並。

  28. git checkout . --恢復上次提交狀態

    • git checkout --file - - 文件在工作區的修改全部撤銷
    • 一種是file修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
    • 一種是file已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
  29. git status – 用於顯示工作目錄和暫存區的狀態。使用此命令能看到那些修改被暫存到了, 哪些沒有, 哪些文件沒有被Git tracked到。git status不顯示已經commit到項目歷史中去的信息。

  30. git reset --hard HEAD^ - - #版本回退

    • git reset --hard commitId - - 取消回退,commitId為你想要回到的未來版本號
    • PS:Git必須知道當前版本是哪個版本,在Git中,用HEAD表示當前版本,上一個版本就是HEAD,上上一個版本就是HEAD^,當回退版本較早時可以寫成HEAD~100。
  31. git stash - - 儲藏可以獲取你工作目錄的中間狀態——也就是你修改過的被追蹤的文件和暫存的變更——並將它保存到一個未完結變更的堆棧中,隨時可以重新應用。
    現在你想切換分支,但是你還不想提交你正在進行中的工作;所以你儲藏這些變更。為了往堆棧推送一個新的儲藏,只要運行git stash。把所有未提交的修改(包括暫存的和非暫存的)都保存起來,用於后續恢復當前工作目錄。
    PS:需要說明一點,stash是本地的,不會通過git push命令上傳到git server上。

  32. git stash list - - 查看現有的所有儲藏,此命令顯然暗示了git stash可以多次保存工作進度,並用在恢復時候選擇。

  33. git stash pop [–index] [ < stash > ] - - 重新應用已經實施的儲藏(刪除儲藏)

    • 如果不使用任何參數,會恢復最新保存的工作進度,並將恢復的工作進度從存儲的工作進度列表中清除。
    • 如果提供< stash>參數(來自git stash list顯示的列表),則從該< stash>中恢復。恢復完畢也將從進度列表中刪除< stash>。
    • 選項–index除了恢復工作區的文件外,還嘗試恢復暫存區。
  34. git stash drop [< stash >] - - 刪除一個存儲的進度。(默認刪除最新的進度)

  35. git stash clear - - 清空當前所有的stash

  36. git stash branch < branchname > < stash > - - 基於儲藏進度創建分支。

三、Git的使用案例與心得

1、場景一:在本地創建工程

在工程目錄里使用:git init,便可初始化一個版本庫

  • 查看本地版本庫的狀態:

    git status

    如圖,可以看到當前本地版本庫與remote的庫的同步情況(remote操作后面再講)。

  • 開始在本地添加工程文件:

    git add HomeWork/Git使用心得體會.md

    此指令會將文件放到暫存區(Index)中,如下圖中的Staged Changes:

  • 再提交到本地版本庫(Repository)當中:

    git commit -m "add HomeWork/Git使用心得體會.md"

  • 版本控制初步:

    • 假設有一個文件"git.md",對它做了四次修改,第i次版本,會將里面內容改成"version i",每次都對其提交。

    git log指令可查看提交記錄:

    ​ 現在欲將其恢復到版本2,則使用命令:git reset --hard HEAD^^ 其中HEAD指向當前分支最新提交的一個版本,一個代表回退一個版本,兩個即可回退到version 2。該指令有多種切換方法:

    git reset —hard HEAD^^/HEAD~100/commit-id/commit-id的頭幾個字符

    • 此時若要返回至version 4,則需要查看commit-id,可使用:git reflog,之后再使用reset指令即可。
    • 所以這么看下來,很像是鏈表操作,HEAD即指針,可移動其切換版本。

2、場景二:與遠程版本庫進行交互

因為Git是分布式的,成員各自編寫的代碼都在本地倉庫,最終完成一個工程肯定要統一合並,一般都合並到GitHub之類的服務器端。但因為寫代碼,彼此之間並不知道對方寫了什么,改了什么,增加了什么,所以在合並時,勢必會有沖突,所以最好是先拉取GitHub的內容與自己的合並,再提交到GitHub,以減少沖突,但仍然不能完全避免沖突。

  1. 先將遠程倉庫拉取下來(fetch/clone 或 pull)

    如果第一次,自然是fetch/clone。否則,需要和遠程同步時,則先需要pull,可以使用git pull [遠程倉庫名] [要拉取的分支]

  2. 再進行push

  • 如果直接push,沖突概率很大,因為在你編寫代碼的時候,同事提交它修改的代碼,而你的寫的和他的就可能有很大不同。所以要先pull,因為遠程倉庫里的東西,是一段時間后“達成的共識”,將它拉取下來基本沒錯,因為它是在比較過提交的各方的代碼之后確定下來的暫時版本。拉取下來之后,也可能會有沖突,自己在本地進行修改,解決沖突部分,這樣也不會因為直接提交到遠程,導致遠程的代碼混亂,使得各個成員也失去了一個標准參照的版本。

  • push即是merge遠程和本地兩個不同的分支

注意:同一分支里的某個版本實際上是對上一個版本的增量補丁,即記錄不同行對比的差異(line diff)。

3、場景三:團隊協作

團隊的每個成員都各自負責不同的某一個功能塊,各占一個分支,各自在本地有一個倉庫,有自己的master和branch,branch下可以有更多的branch,最后成員完成時,將自己的分支合並到自己的master,再提交到服務器端。

  • 合並的分類

    (1) 快進式合並

    這個在合並的時候會將分支和主線合並成一條時間線,如圖:

    (2) 相對應的,要體現多條分支,須使用:--no-ff參數

    ​比如:git merge --no-ff mybranch

  • 截取一段分支合並圖,可見,很像一個有向無環的活動圖。帶箭頭的有向邊相當於活動,圖中的點相當於事件,或者說是一個版本。在多人合作當中,可以並行進行,但效率取決於關鍵路徑的長短,即如果有人進度落后,是不能按時合並成一個期望的版本的。

4、場景四:GitBase

本地與服務端的同步,即pull再push,pull實際上就是將兩個分支(本地分支和服務器分支)merge,這就會表現出兩條分支線:

實際上可以用另外一種方法,讓分支歷史看起來像沒有經過任何合並一樣,用 git rebase:

  • gitbase的原理:

    這個命令會把"mywork"分支里的每個提交(commit)取消掉,並且把它們臨時 保存為補丁(patch)(這些補丁放到".git/rebase"目錄中),然后把"mywork"分支更新 為最新的"origin"分支,最后把保存的這些補丁應用到"mywork"分支上。當"mywork"分支更新之后,它會指向這些新創建的提交(commit),而那些老的提交會被丟棄。

  • 沖突的解決:

    在rebase的過程中,也許會出現沖突(conflict). 在這種情況,Git會停止rebase並會讓你去解決沖突;在解決完沖突后,用git-add命令去更新這些內容的索引(index), 然后,無需執行git -commit, 只要執行:

    git rebase --continue

    這樣git會繼續應用(apply)余下的補丁。

    在任何時候,你可以用--abort參數來終止rebase的行動,並且"mywork" 分支會回到rebase開始前的狀態。

    git rebase --abort

5、場景五:Fork + Pull request

如果向開源項目貢獻代碼,則需要先fork一下別人的倉庫(即拷貝),當寫完自己的代碼后,發起Pull request給原倉庫,原倉庫的所有者來決定要不要merge進去。

  • 例如,在github上fork一個gitignore項目,里面有很多寫好的.gitignore文件:

  • 之后便看到這個倉庫進了自己的,如果自己有添加或修改了代碼,可以點擊Pull request:

  • 提交之后,在原倉庫的Pull request里看到提交的請求:

參考鏈接:

https://blog.csdn.net/weixin_43606158/article/details/90729743

https://blog.csdn.net/hudashi/article/details/7664631/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM