<optgroup id="6y7f6"><small id="6y7f6"></small></optgroup>

<code id="6y7f6"></code>

  • <p id="6y7f6"><tbody id="6y7f6"><ins id="6y7f6"></ins></tbody></p>
    <code id="6y7f6"><form id="6y7f6"></form></code>

      Git入門圖文教程(1.5W字40圖)🔥🔥--深入淺出、圖文并茂

      image.png

      01、認識一下Git!—簡介

      Git是當前最先進、最主流的分布式版本控制系統,免費、開源!核心能力就是版本控制。再具體一點,就是面向代碼文件的版本控制,代碼的任何修改歷史都會被記錄管理起來,意味著可以恢復到到以前的任意時刻狀態。支持跨區域多人協作編輯,是團隊項目開發的必備基礎,所以Git也就成了程序員的必備技能。

      image

      ??主要特點

      • 開源免費,使用廣泛。
      • 強大的文檔(代碼)的歷史版本管理,直接記錄完整快照(完整內容,而非差異),支持回滾、對比。
      • 分布式多人協作的的代碼協同開發,幾乎所有操作都是本地執行的,支持代碼合并、代碼同步。
      • 簡單易用的分支管理,支持高效的創建分支、合并分支。

      image.png

      Git是Linux之父被迫開發的,為了解決Linux混亂的代碼管理而開發的。Linux和Git之父 李納斯·托沃茲(Linus Benedic Torvalds),來自1969年的芬蘭。


      02、Git是干什么的?—基礎概念

      先了解下Git的基本概念,及基本框架、工作流程。

      2.1、Git概念匯總??

      概念名稱 描述
      工作區(Workspace) 就是在電腦里能看到的代碼庫目錄,是我們搬磚的地方,新增、修改的文件會提交到暫存區
      暫存區(stage 或 index) 用于臨時存放文件的修改,實際上上它只是一個文件(.git/index),保存待提交的文件列表信息。
      版本庫/倉庫(Repository) Git的管理倉庫,管理版本的數據庫,記錄文件/目錄狀態的地方,所有內容的修改記錄(版本)都在這里。
      服務端/遠程倉庫(origin 或 remote) 服務端的版本庫,專用的Git服務器,為多人共享提供服務,承擔中心服務器的角色。本地版本庫通過push指令把代碼推送到服務端版本庫。
      本地倉庫 用戶機器上直接使用的的的版本庫
      分支(Branch) 分支是從主線分離出去的“副本”,可以獨立操作而互不干擾,倉庫初始化就有一個默認主分支master。
      (HEAD) HEAD類似一個“指針”,指向當前活動 分支最新版本。
      提交(Commit) 把暫存區的所有變更的內容提交到當前倉庫的活動分支。
      推送(Push) 將本地倉庫的版本推送到服務端(遠程)倉庫,與他人共享。
      拉取(Pull) 從服務端(遠程)倉庫獲取更新到本地倉庫,獲取他人共享的更新。
      獲取(Fetch) 從服務端(遠程)倉庫更新,作用同拉?。≒ull),區別是不會自動合并。
      沖突(Conflict) 多人對同一文件的工作副本進行更改,并將這些更改合并到倉庫時就會面臨沖突,需要人工合并處理。
      合并(Merge) 對有沖突的文件進行合并操作,Git會自動合并變更內容,無法自動處理的沖突內容會提示人工處理。
      標簽(Tags) 標簽指的是某個分支某個特定時間點的狀態,可以理解為提交記錄的別名,常用來標記版本。
      master(或main) 倉庫的“master”分支,默認的主分支,初始化倉庫就有了。Github上創建的倉庫默認名字為“main
      origin/master 表示遠程倉庫(origin)的“master”分支
      origin/HEAD 表示遠程倉庫(origin)的最新提交的位置,一般情況等于“origin/master

      2.2、工作區/暫存區/倉庫

      image.png

      工作區、暫存區、版本庫是Git最基本的概念,關系如下圖:

      image

      ??工作區(Workspace)就是在電腦里能看到的代碼庫目錄,是我們搬磚的地方,新增、修改的文件會提交到暫存區。

      • 在這里新增文件、修改文件內容,或刪除文件。

      ??暫存區(stage或index) 用于臨時存放文件的修改,實際上上它只是一個文件(.git/index),保存待提交的文件列表信息。

      • git add 命令將工作區的修改保存到暫存區。

      ??版本庫/倉庫(Repository /r??pɑ?z?t??ri/ 倉庫)Git的管理倉庫,管理版本的數據庫,記錄文件/目錄狀態的地方,所有內容的修改記錄(版本)都在這里。就是工作區目錄下的隱藏文件夾.git,包含暫存區、分支、歷史記錄等信息。

      • git commit 命令將暫存區的內容正式提交到版本庫。
      • master 為倉庫的默認分支master,HEAD是一個“指針”指向當前分支的最新提交,默認指向最新的master。

      image

      如上圖,為對應本地倉庫目錄的結構關系。

      • KWebNote為項目目錄,也就是Git工作區。
      • 項目根目錄下隱藏的.git目錄就是Git倉庫目錄了,存放了所有Git管理的信息。
      • .git/config為該倉庫的配置文件,可通過指令修改或直接修改。
      • index文件就是存放的暫存區內容。

      2.3、Git基本流程(圖)

      Git的工作流程核心就下面幾個步驟,掌握了就可以開始寫Bug了。

      • 0、準備倉庫:創建或從服務端克隆一個倉庫。
      • 1、搬磚:在工作目錄中添加、修改代碼。
      • 2、暫存(git add):將需要進行版本管理的文件放入暫存區域。
      • 3、提交(git commit):將暫存區域的文件提交到Git倉庫。
      • 4、推送(git push):將本地倉庫推送到遠程倉庫,同步版本庫。
      • 5、獲取更新(fetch/pull):從服務端更新到本地,獲取他人推送的更新,與他人協作、共享。

      image

      • git commit -a指令省略了add到暫存區的步驟,直接提交工作區的修改內容到版本庫,不包括新增的文件。
      • git fetch、git pull 都是從遠程服務端獲取最新記錄,區別是git pull多了一個步驟,就是自動合并更新工作區。
      • git checkout .、git checkout [file] 會清除工作區中未添加到暫存區的修改,用暫存區內容替換工作區。
      • git checkout HEAD .、 git checkout HEAD [file] 會清除工作區、暫存區的修改,用HEAD指向的當前分支最新版本替換暫存區、工作區。
      • git diff 用來對比不同部分之間的區別,如暫存區、工作區,最新版本與未提交內容,不同版本之間等。
      • git reset是專門用來撤銷修改、回退版本的指令,替代上面checkout的撤銷功能。

      2.4、Git狀態(圖)

      Git在執行提交的時候,不是直接將工作區的修改保存到倉庫,而是將暫存區域的修改保存到倉庫。要提交文件,首先需要把文件加入到暫存區域中。因此,Git管理的文件有三(+2)種狀態:

      • 未跟蹤(untracked):新添加的文件,或被移除跟蹤的文件,未建立跟蹤,通過git add添加暫存并建立跟蹤。
      • 未修改:從倉庫簽出的文件默認狀態,修改后就是“已修改”狀態了。
      • 已修改(modified):文件被修改后的狀態。
      • 已暫存(staged):修改、新增的文件添加到暫存區后的狀態。
      • 已提交(committed):從暫存區提交到版本庫。

      image


      03、起步:Git安裝配置

      Git官網:https://www.git-scm.com/ 下載安裝包進行安裝。Git的使用有兩種方式:

      • 命令行:Git的命令通過系統命令行工具,或Git提供的命令行工具運行(C:\Program Files\Git\git-bash.exe
      • GUI工具:Windows(GUI)、Mac(GUI)工具,需單獨安裝,使用更簡單、更易上手。

      指令git --version查看安裝版本號

      $ git --version
      git version 2.33.0.windows.2
      

      ?? 本文是在Windows 平臺上完成的,不過這個對學習Git沒什么影響。

      3.1、Git的配置文件

      Git有三個主要的配置文件:三個配置文件的優先級是① < ② < ③

      • ① 系統全局配置(--system):包含了適用于系統所有用戶和所有倉庫(項目)的配置信息,存放在Git安裝目錄下C:\Program Files\Git\etc\gitconfig。
      • ② 用戶全局配置(--global):當前系統用戶的全局配置,存放用戶目錄:C:\Users\[系統用戶名]\.gitconfig。
      • ③ 倉庫/項目配置(--local):倉庫(項目)的特定配置,存放在項目目錄下.git/config

      image

      #查看git配置
      git config --list
      git config -l
      
      #查看系統配置
      git config --system --list
      
      #查看當前用戶(global)全局配置
      git config --list --global
      
      #查看當前倉庫配置信息
      git config --local  --list
      

      倉庫的配置是上面多個配置的集合:

      $ git config --list
      $ git config -l
      diff.astextplain.textconv=astextplain
      http.sslbackend=openssl
      http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
      core.autocrlf=true
      core.fscache=true
      core.symlinks=false
      pull.rebase=false
      credential.helper=manager-core
      credential.https://dev.azure.com.usehttppath=true
      init.defaultbranch=master
      user.name=Kanding
      user.email=123anding@163.com
      

      3.2、配置-初始化用戶

      當安裝Git后首先要做的事情是配置你的用戶信息—— 告訴Git你是誰?配置 用戶名、郵箱地址,每次提交文件時都會帶上這個用戶信息,查看歷史記錄時就知道是誰干的了。

      配置用戶信息:

      $ git config --global user.name "Your Name"
      $ git config --global user.email "email@example.com"
      # 配置完后,看看用戶配置文件:
      $ cat 'C:\Users\Kwongad\.gitconfig'
      [user]
              name = Kanding
              email = 123anding@163.com
      
      • user.name為用戶名,user.email為郵箱。
      • --globalconfig的參數,表示用戶全局配置。如果要給特定倉庫配置用戶信息,則用參數--local配置即可,或直接在倉庫配置文件.git/config里修改。

      3.3、配置-忽略.gitignore

      工作目錄中的文件并不是全都需要納入版本管理,如日志、臨時文件、私有配置文件等不需要也不能納入版本管理,那該怎么辦呢?

      image.png

      在工作區根目錄下創建“.gitignore”文件,文件中配置不需要進行版本管理的文件、文件夾?!?code>.gitignore”文件本身是被納入版本管理的,可以共享。有如下規則:

      • #符號開頭為注釋。
      • 可以使用Linux通配符。
        • 星號(*)代表任意多個字符,
        • 問號(?)代表一個字符,
        • 方括號([abc])代表可選字符范圍,
        • 大括號({string1,string2,...})代表可選的字符串等。
      • 感嘆號(!)開頭:表示例外規則,將不被忽略。
      • 路徑分隔符(/f)開頭:,表示要忽略根目錄下的文件f。
      • 路徑分隔符(f/)結尾:,表示要忽略文件夾f下面的所有文件。
      #為注釋
      *.txt #忽略所有“.txt”結尾的文件
      !lib.txt #lib.txt除外
      /temp #僅忽略項目根目錄下的temp文件,不包括其它目錄下的temp,如不包括“src/temp”
      build/ #忽略build/目錄下的所有文件
      doc/*.txt #會忽略 doc/notes.txt 但不包括 doc/server/arch.txt
      

      ?? 各種語言項目的常用.gitignore文件配置:https://github.com/github/gitignore


      04、Git的GUI工具們

      如果不想用命令行工具,完全可以安裝一個Git的GUI工具,用的更簡單、更舒服。不用記那么多命令了,極易上手,不過Git基礎還是需要學習了解一下的。

      ?對于Git,建議用命令行,這樣你才能真的理解Git的思想?
      ??其實都只是工具而已,適合自己的就是最好的,沒必要糾結,多寫點Bug更重要!

      • TortoiseGit:小烏龜,SVN時代就很流行的代碼管理GUI利器。
        • ??只有Windows版本,支持中文,需要單獨下載安裝中文語言包。
        • ??開源,免費,與文件管理器的良好集成。
        • ??內置沖突對比解決工具。
      • Sourcetree:SourceTree是老牌的Git GUI管理工具了,也號稱是最好用的Git GUI工具。
        • ??適用于 Windows 和 Mac 系統,內置中文版,自動識別語言。
        • ??免費、功能強大,使用簡單。
        • ??功能豐富,基本操作和高級操作都設計得非常流暢,適合初學者上手,支持Git Flow。
        • ??無沖突對比工具,支持配置第三方組件。
      • GitHub Desktop:Github官方出品的Git管理工具。
      • GitKraken:GitKraken是一個跨平臺GUI Git客戶端,有免費版,專業版和企業版,這些版本啟用了不同的功能。

      4.1、SourceTree

      SourceTree的官網 下載安裝包,支持Window、Mac系統,按照提示完成安裝。

      • SourceTree支持管理多個倉庫,通過+按鈕,可選擇多種方式添加倉庫。

      image.png

      • 然后就是可視化的倉庫管理了,不用記住繁瑣的指令(參數)了,可視化操作。

      image

      4.2、TortoiseGit

      image.png

      TortoiseGit 官網下載安裝包,及中文語言包,按照提示完成安裝。小烏龜的Git是集成到操作系統里的,直接右鍵文件夾就可以進行Git操作了。

      image.png

      • 先進入設置:右鍵文件夾菜單 --> TortoiseGit --> Settings 進入設置,設置中文語言。
      • 小烏龜的各種Git操作都在右鍵菜單了,深度集成到了操作系統的資源管理器中了,文件圖標也是有Git狀態的,比較容易分辨。

      image.png

      image.png

      4.3、VSCode中的Git

      VSCode自帶的Git工具基本已經可以滿足日常使用了,既有可視化功能,也能敲命令,習慣了不就不用安裝其他GUI工具了。不過還是可以再安裝一些VSCode插件,來增強Git功能。

      • GitLens :在團隊項目開發中非常實用,必備?。?!用于快速查看代碼提交歷史記錄,在代碼上會顯示最近的修改信息,包括提交者,只就這一點就值得推薦了。

      image.png

      • Git History:可以輕松快速瀏覽Git文件操作歷史記錄的工具,可視化展示,操作簡單。

      05、Git使用入門

      5.1、創建倉庫

      創建本地倉庫的方法有兩種:

      • 一種是創建全新的倉庫:git init,會在當前目錄初始化創建倉庫。
      • 另一種是克隆遠程倉庫:git clone [url]
      # 準備一個文件夾“KwebNote”作為倉庫目錄,命令行進入該文件夾
      Kwongad@Kwongad-T14 MINGW64 ~
      $ cd d:
      Kwongad@Kwongad-T14 MINGW64 /d
      $ cd Project_Files
      Kwongad@Kwongad-T14 MINGW64 /d/Project_Files
      # 多次cd指令進入到倉庫目錄KwebNote:“cd <目錄名稱>”指令進入目錄,“cd ..”返回上級目錄(有空格)
      Kwongad@Kwongad-T14 MINGW64 /d/Project_Files/github.kwong/KwebNote
      
      # 開始初始化項目,也可指定目錄:git init [文件目錄]
      $ git init
      Initialized empty Git repository in D:/Project_Files/github.Kwong/KwebNote/.git/
      

      ??注意:Git指令的執行,都需在倉庫目錄下。

      創建完多出了一個被隱藏的.git目錄,這就是本地倉庫Git的工作場所。

      image.png

      克隆遠程倉庫,如在github上創建的倉庫“https://github.com/kwonganding/KWebNote.git

      $ git clone 'https://github.com/kwonganding/KWebNote.git'
      Cloning into 'KWebNote'...
      remote: Enumerating objects: 108, done.
      remote: Counting objects: 100% (108/108), done.
      remote: Compressing objects: 100% (60/60), done.
      remote: Total 108 (delta 48), reused 88 (delta 34), pack-reused 0
      Receiving objects: 100% (108/108), 9.36 KiB | 736.00 KiB/s, done.
      Resolving deltas: 100% (48/48), done.
      

      會在當前目錄下創建“KWebNote”項目目錄。

      image.png

      5.2、暫存區add

      可以簡單理解為,git add命令就是把要提交的所有修改放到暫存區(Stage),然后,執行git commit就可以一次性把暫存區的所有修改提交到倉庫。

      指令 描述
      git add [file1] [file2] 添加文件到暫存區,包括修改的文件、新增的文件
      git add [dir] 同上,添加目錄到暫存區,包括子目錄
      git add . 同上,添加所有修改、新增文件(未跟蹤)到暫存區
      git rm [file] 刪除工作區文件,并且將這次刪除放入暫存區
      # 添加指定文件到暫存區,包括被修改的文件
      $ git add [file1] [file2] ...
      
      # 添加當前目錄的所有文件到暫存區
      $ git add .
      
      # 刪除工作區文件,并且將這次刪除放入暫存區
      $ git rm [file1] [file2] ...
      
      # 改名文件,并且將這個改名放入暫存區
      $ git mv [file-original] [file-renamed]
      

      修改文件“R.md”,未暫存:

      image.png

      執行git add .暫存:

      image.png

      5.3、提交commit-記錄

      git commit提交是以時間順序排列被保存到數據庫中的,就如游戲關卡一樣,每一次提交(commit)就會產生一條記錄:id + 描述 + 快照內容。

      • ??commit id:根據修改的文件內容采用摘要算法(SHA1)計算出不重復的40位字符,這么長是因為Git是分布式的,要保證唯一性、完整性,一般本地指令中可以只用前幾位(6)。即使多年以后,依然可通過id找到曾經的任何內容和變動,再也不用擔心丟失了。
      • ??描述:針對本次提交的描述說明,建議準確填寫,就跟代碼中的注釋一樣,很重要。
      • ??快照:就是完整的版本文件,以對象樹的結構存在倉庫下\.git\objects目錄里,這也是Git效率高的秘訣之一。
      • SHA1 是一種哈希算法,可以用來生成數據摘要
      • Git不適合大的非文本文件,會影響計算摘要、快照的性能。

      多個提交就形成了一條時間線,每次提交完,會移動當前分支master、HEAD的“指針”位置。

      image

      Sourcetree上的歷史記錄:

      image.png

      ??一般情況,每完成一個小功能、一個Bu就可以提交一次,這樣會形成比較清晰的歷史記錄。

      ??指令:

      指令 描述
      git commit -m '說明' 提交變更,參數-m設置提交的描述信息,應該正確提交,不帶該參數會進入說明編輯模式
      git commit -a 參數-a,表示直接從工作區提交到版本庫,略過了git add步驟,不包括新增的文件
      git commit [file] 提交暫存區的指定文件到倉庫區
      git commit --amend -m 使用一次新的commit,替代上一次提交,會修改commithash值(id)
      git log -n20 查看日志(最近20條),不帶參數-n則顯示所有日志
      git log -n20 --oneline 參數“--oneline”可以讓日志輸出更簡潔(一行)
      git log -n20 --graph 參數“--graph”可視化顯示分支關系
      git log --follow [file] 顯示某個文件的版本歷史
      git blame [file] 以列表形式顯示指定文件的修改記錄
      git reflog 查看所有可用的歷史版本記錄(實際是HEAD變更記錄),包含被回退的記錄(重要
      git status 查看本地倉庫狀態,比較常用的指令,加參數-s簡潔模式

      image

      通過git log指令可以查看提交記錄日志,可以很方便的查看每次提交修改了哪些文件,改了哪些內容,從而進行恢復等操作。

      # 提交暫存區到倉庫區
      $ git commit -m [message]
      # 提交所有修改到倉庫
      $ git commit -a -m'修改README的版權信息'
      
      # 提交暫存區的指定文件到倉庫區
      $ git commit [file1] [file2] ... -m [message]
      
      # 使用一次新的commit,替代上一次提交
      # 如果代碼沒有任何新變化,則用來改寫上一次commit的提交信息
      $ git commit --amend -m [message]
      
      $ git log -n2
      commit 412b56448568ff362ef312507e78797befcf2846 (HEAD -> main)
      Author: Kanding <123anding@163.com>
      Date:   Thu Dec 1 19:02:22 2022 +0800
      
      commit c0ef58e3738f7d54545d8c13d603cddeee328fcb
      Author: Kanding <123anding@163.com>
      Date:   Thu Dec 1 16:52:56 2022 +0800
      
      # 用參數“--oneline”可以讓日志輸出更簡潔(一行)
      $ git log -n2 --oneline
      5444126 (HEAD -> main, origin/main, origin/HEAD) Update README.md
      228362e Merge branch 'main' of github.com:kwonganding/KWebNote
      

      5.4、Git的“指針”引用們

      Git中最重要的就是提交記錄了,其他如標簽、分支、HEAD 都對提交記錄的“指針”引用,指向這些提交記錄,理解這一點很重要。

      • 提交記錄之間也存在“指針”引用,每個提交會指向其上一個提交。
      • 標簽 就是對某一個提交記錄的的 固定 “指針”引用,取一個別名更容易記憶一些關鍵節點。存儲在工作區根目錄下.git\refs\tags。
      • 分支 也是指向某一個提交記錄的“指針”引用,“指針”位置可變,如提交、更新、回滾。存儲在工作區根目錄下.git\refs\heads。
      • HEAD:指向當前活動分支(最新提交)的一個“指針”引用,存在在“.git/HEAD”文件中,存儲的內容為“ref: refs/heads/master”。

      image

      上圖中:

      • HEAD始終指向當前活動分支,多個分支只能有一個處于活動狀態。
      • 標簽t1在某一個提交上創建后,就不會變了。而分支、HEAD的位置會改變。

      打開這些文件內容看看,就更容易理解這些“指針”的真面目了。

      # tag
      $ git tag -a 'v1' -m'v1版本'
      $ cat .git/refs/tags/v1
      a2e2c9caea35e176cf61e96ad9d5a929cfb82461
      
      # main分支指向最新的提交
      $ cat .git/refs/heads/main
      8f4244550c2b6c23a543b741c362b13768442090
      
      # HEAD指向當前活動分支
      $ cat .git/HEAD
      ref: refs/heads/main
      
      # 切換到dev分支,HEAD指向了dev
      $ git switch dev
      Switched to branch 'dev'
      $ cat .git/HEAD
      ref: refs/heads/dev
      

      這里的主分支名字為“main”,是因為該倉庫是從Github上克隆的,Github上創建的倉庫默認主分支名字就是“main”,本地創建的倉庫默認主分支名字為“master”。

      ??“指針”引用:之所以用引號的“指針”,是為了便于統一和理解。和指針原理類似,都是一個指向,只是實際上可能更復雜一點,且不同的“指針”引用會有區別。

      5.5、提交的唯一標識id,HEAD~n是什么意思?

      每一個提交都有一個唯一標識,主要就是提交的hashcommit id,在很多指令中會用到,如版本回退、揀選提交等,需要指定一個提交。那標識唯一提交有兩種方式:

      • 首先就是commit id,一個40位編碼,指令中使用的時候可以只輸入前幾位(6位)即可。
      • 還有一種就是HEAD~n,是基于當前HEAD位置的一個相對坐標。
        • HEAD 表示當前分支的最新版本,是比較常用的參數。
        • HEAD^上一個版本,HEAD^^ 上上一個版本。
        • HEAD~HEAD~1 表示上一個版本,以此類推,HEAD^10 為最近第10個版本。
        • HEAD@{2}git reflog日志中標記的提交記錄索引。

      通過git log、git reflog可以查看歷史日志,可以看每次提交的唯一編號(hash)。區別是git reflog可以查看所有操作的記錄(實際是HEAD變更記錄),包括被撤銷回退的提交記錄。

      $ git reflog -n10
      5acc914 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~
      738748b (dev) HEAD@{1}: reset: moving to HEAD~
      9312c3e HEAD@{2}: reset: moving to HEAD~
      db03fcb HEAD@{3}: reset: moving to HEAD~
      1b81fb3 HEAD@{4}: reset: moving to HEAD~
      41ea423 HEAD@{5}: reset: moving to HEAD~
      d3e15f9 HEAD@{6}: reset: moving to d3e15f9
      1b81fb3 HEAD@{7}: reset: moving to HEAD~1
      41ea423 HEAD@{8}: reset: moving to HEAD~
      d3e15f9 HEAD@{9}: reset: moving to HEAD~
      

      5.6、比較diff

      git diff用來比較不同文件版本之間的差異。

      指令 描述
      git diff 查看暫存區和工作區的差異
      git diff [file] 同上,指定文件
      git diff --cached 查看已暫存的改動,就是暫存區與新版本HEAD進行比較
      git diff --staged 同上
      git diff --cached [file] 同上,指定文件
      git diff HEAD 查看已暫存的+未暫存的所有改動,就是與最新版本HEAD進行比較
      git diff HEAD~ 同上,與上一個版本比較。HEAD~表示上一個版本,HEAD~10為最近第10個版本
      git diff [id] [id] 查看兩次提交之間的差異
      git diff [branch] 查看工作區和分支直接的差異

      ??畫個圖更清晰些:

      image

      # 查看文件的修改
      $ git diff README.md
      
      # 查看兩次提交的差異
      $ git diff 8f4244 1da22
      
      # 顯示今天你寫了多少行代碼:工作區+暫存區
      $ git diff --shortstat "@{0 day ago}"
      

      06、遠程倉庫

      Git作為分布式的版本管理系統,每個終端都有自己的Git倉庫。但團隊協作還需一個中間倉庫,作為中心,同步各個倉庫。于是服務端(遠程)倉庫就來承擔這個職責,服務端不僅有倉庫,還配套相關管理功能。

      image

      可以用公共的Git服務器,也可以自己搭建一套Git服務器。

      6.1、遠程用戶登錄

      Git服務器一般提供兩種登錄驗證方式:

      • HTTS:基于HTTPS連接,使用用戶名、密碼身份驗證。
        • 每次都要輸入用戶名、密碼,當然可以記住。
        • 地址形式:https://github.com/kwonganding/KWebNote.git
      • SSL:采用SSL通信協議,基于公私鑰進行身份驗證,所以需要額外配置公私秘鑰。
        • 不用每次輸入用戶名、密碼,比較推薦的方法。
        • 地址形式:git@github.com:kwonganding/KWebNote.git

      image.png

      #查看當前遠程倉庫使用的那種協議連接:
      $ git remote -v
      origin  git@github.com:kwonganding/KWebNote.git (fetch)
      origin  https://github.com/kwonganding/KWebNote.git (push)
      
      # 更改為https地址,即可切換連接模式。還需要禁用掉SSL, 才能正常使用https管理git
      git config --global http.sslVerify false
      

      ??遠程用戶登錄:HTTS

      基于HTTPS的地址連接遠程倉庫,Github的共有倉庫克隆、拉?。╬ull)是不需要驗證的。

      image.png

      $ git clone 'https://github.com/kwonganding/KWebNote.git'
      Cloning into 'KWebNote'...
      
      # 倉庫配置文件“.git/config”
      [remote "origin"]
       	url = https://github.com/kwonganding/KWebNote.git
      	fetch = +refs/heads/*:refs/remotes/origin/*
      	pushurl = https://github.com/kwonganding/KWebNote.git
      

      推送(push)代碼的時候就會提示輸入用戶名、密碼了,否則無法提交。記住用戶密碼的方式有兩種:

      • ??URL地址配置:在原本URL地址上加上用戶名、密碼,https://后加用戶名:密碼@
      # 直接修改倉庫的配置文件“.git/config”
      [remote "origin"]
       	url = https://用戶名:密碼@github.com/kwonganding/KWebNote.git
      	fetch = +refs/heads/*:refs/remotes/origin/*
      	pushurl = https://github.com/kwonganding/KWebNote.git
      
      • ??本地緩存:會創建一個緩存文件.git-credentials,存儲輸入的用戶名、密碼。
      # 參數“--global”全局有效,也可以針對倉庫設置“--local”
      # store 表示永久存儲,也可以設置臨時存儲
      git config --global credential.helper store
      
      # 存儲內容如下,打開文件“倉庫\.git\.git-credentials”
      https://kwonganding:[加密內容付費可見]@github.com
      

      ??遠程用戶登錄:SSH

      image.png

      SSH(Secure Shell,安全外殼)是一種網絡安全協議,通過加密和認證機制實現安全的訪問和文件傳輸等業務,多用來進行遠程登錄、數據傳輸。SSH通過公鑰、私鑰非對稱加密數據,所以SSH需要生成一個公私鑰對,公鑰放服務器上,私有自己留著進行認證。

      ① 生成公私鑰:通過Git指令ssh-keygen -t rsa生成公私鑰,一路回車即可完成。生成在“C:\Users\用戶名\.ssh”目錄下,文件id_rsa.pub的內容就是公鑰。

      image.png

      ② 配置公鑰:打開id_rsa.pub文件,復制內容。Github上,打開Setting? SSH and GPG keys ? SSH keys ? 按鈕New SSH key,標題(Title)隨意,秘鑰內容粘貼進去即可。

      image.png

      SSH配置完后,可用ssh -T git@github.com來檢測是否連接成功。

      $ ssh -T git@github.com
      Hi kwonganding! You've successfully authenticated, but GitHub does not provide shell access.
      

      6.2、遠程倉庫指令??

      指令 描述
      git clone [git地址] 從遠程倉庫克隆到本地(當前目錄)
      git remote -v 查看所有遠程倉庫,不帶參數-v只顯示名稱
      git remote show [remote] 顯示某個遠程倉庫的信息
      git remote add [name] [url] 增加一個新的遠程倉庫,并命名
      git remote rename [old] [new] 修改遠程倉庫名稱
      git pull [remote] [branch] 取回遠程倉庫的變化,并與本地版本合并
      git pull 同上,針對當前分支
      git fetch [remote] 獲取遠程倉庫的所有變動到本地倉庫,不會自動合并!需要手動合并
      git push 推送當前分支到遠程倉庫
      git push [remote] [branch] 推送本地當前分支到遠程倉庫的指定分支
      git push [remote] --force/-f 強行推送當前分支到遠程倉庫,即使有沖突,??很危險!
      git push [remote] --all 推送所有分支到遠程倉庫
      git push –u 參數–u表示與遠程分支建立關聯,第一次執行的時候用,后面就不需要了
      git remote rm [remote-name] 刪除遠程倉庫
      git pull --rebase 使用rebase的模式進行合并

      6.3、推送push/拉取pull

      git push、git pull是團隊協作中最常用的指令,用于同步本地、服務端的更新,與他人協作。

      ??推送(push):推送本地倉庫到遠程倉庫。

      • 如果推送的更新與服務端存在沖突,則會被拒絕,push失敗。一般是有其他人推送了代碼,導致文件沖突,可以先pull代碼,在本地進行合并,然后再push。

      ??拉取(pull):從服務端(遠程)倉庫更新到本地倉庫。

      • git pull:拉取服務端的最新提交到本地,并與本地合并,合并過程同分支的合并。
      • git fetch:拉取服務端的最新提交到本地,不會自動合并,也不會更新工作區。

      image

      6.4、fetch與pull有什么不同?

      兩者都是從服務端獲取更新,主要區別是fetch不會自動合并,不會影響當前工作區內容。

      git pull = git fetch + git merge

      • 如下面圖中,git fetch只獲取了更新,并未影響master、HEAD的位置。
      • 要更新master、HEAD的位置需要手動執行git merge合并。

      image

      # fetch只更新版本庫
      $ git fetch
      remote: Enumerating objects: 5, done.
      remote: Counting objects: 100% (5/5), done.
      remote: Compressing objects: 100% (3/3), done.
      remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
      Unpacking objects: 100% (3/3), 663 bytes | 44.00 KiB/s, done.
      From github.com:kwonganding/KWebNote
         2ba12ca..c64f5b5  main       -> origin/main
      
      # 執行合并,合并自己
      $ git merge
      Updating 2ba12ca..c64f5b5
      Fast-forward
       README.md | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      

      07、Git利器-分支

      分支是從主線分離出去的“副本”,分支就像是平行宇宙,可獨立發展,獨立編輯、提交,也可以和其他分支合并。分支是Git的核心必殺利器之一,分支創建、切換、刪除都非???,他非常的輕量。所以,早建分支!多用分支!

      image.png

      7.1、分支Branch

      比如有一個項目團隊,準備10月份發布新版本,要新開發一堆黑科技功能,占領市場。你和小伙伴“小美”一起負責開發一個新功能A,開發周期2周,在這兩周你們的代碼不能影響其他人,不影響主分支。這個時候就可以為這個新功能創建一個分支,你們兩在這個分支上干活,2周后代碼開發完了、測試通過,就可以合并進要發版的開發分支了。安全、高效,不影響其他人工作,完美!

      image

      在實際項目中,一般會建幾個主線分支。

      • ??master:作為主分支,存放穩定的代碼,就是開發后測試通過的代碼,不允許隨便修改和合并。
      • ??開發分支:用于團隊日常開發用,比如團隊計劃10月份開發10個功能并發版,則在此分支上進行,不影響主分支的穩定。
      • ??功能A分支:開發人員根據自己的需要,可以創建一些臨時分支用于特定功能的開發,開發完畢后再合并到開發分支,并刪除該分支。

      分支就是指向某一個提交記錄的“指針”引用,因此創建分支是非??斓?,不管倉庫多大。當我們運行git branch dev創建了一個名字為dev的分支,Git實際上是在.git\refs\heads下創建一個dev的引用文件(沒有擴展名)。

      $ git branch dev
      $ cat .git/refs/heads/dev
      ca88989e7c286fb4ba56785c2cd8727ea1a07b97
      

      7.2、分支指令??

      指令 描述
      git branch 列出所有本地分支,加參數-v顯示詳細列表,下同
      git branch -r 列出所有遠程分支
      git branch -a 列出所有本地分支和遠程分支,用不同顏色區分
      git branch [branch-name] 新建一個分支,但依然停留在當前分支
      git branch -d dev 刪除dev分支,-D(大寫)強制刪除
      git checkout -b dev 從當前分支創建并切換到dev分支
      git checkout -b feature1 dev 從本地dev分支代碼創建一個 feature1分支,并切換到新分支
      git branch [branch] [commit] 新建一個分支,指向指定commit id
      git branch --track [branch] [remote-branch] 新建一個分支,與指定的遠程分支建立關聯
      git checkout -b hotfix remote hotfix 從遠端remotehotfix分支創建本地hotfix分支
      git branch --set-upstream [branch] [remote-branch] 在現有分支與指定的遠程分支之間建立跟蹤關聯:
      git branch --set-upstream hotfix remote/hotfix
      git checkout [branch-name] 切換到指定分支,并更新工作區
      git checkout . 撤銷工作區的(未暫存)修改,把暫存區恢復到工作區。
      git checkout HEAD . 撤銷工作區、暫存區的修改,用HEAD指向的當前分支最新版本替換
      git merge [branch] 合并指定分支到當前分支
      git merge --no-ff dev 合并dev分支到當前分支,參數--no-ff禁用快速合并模式
      git push origin --delete [branch-name] 刪除遠程分支
      git rebase master 將當前分支變基合并到master分支
      ?switch:新的分支切換指令 切換功能和checkout一樣,switch只單純的用于切換
      git switch master 切換到已有的master分支
      git switch -c dev 創建并切換到新的dev分支

      ??關于 checkout 指令checkout是Git的底層指令,比較常用,也比較危險,他會重寫工作區。支持的功能比較多,能撤銷修改,能切換分支,這也導致了這個指令比較復雜。在Git 2.23版本以后,增加了git switch、git reset指令。

      • git switch:專門用來實現分支切換。
      • git reset:專門用來實現本地修改的撤銷,更多可參考后續“reset”內容。
      $ git branch
        dev
      * main
      # 列出了當前的所有分支,星號“*”開頭的“main”為當前活動分支。
      

      7.3、分支的切換checkout

      代碼倉庫可以有多個分支,master為默認的主分支,但只有一個分支在工作狀態。所以要操作不同分支,需要切換到該分支,HEAD就是指向當前正在活動的分支。

      image

      # 切換到dev分支,HEAD指向了dev
      # 此處 switch 作用同 checkout,switch只用于切換,不像checkout功能很多
      $ git switch dev
      Switched to branch 'dev'
      $ cat .git/HEAD
      ref: refs/heads/dev
      

      使用 git checkout dev切換分支時,干了兩件事:

      • ①、HEAD指向dev:修改HEAD的“指針”引用,指向dev分支。
      • ②、還原工作空間:把dev分支內容還原到工作空間。

      此時的活動分支就是dev了,后續的提交就會更新到dev分支了。

      ?切換時還沒提交的代碼怎么辦?

      • 如果修改(包括未暫存、已暫存)和待切換的分支沒有沖突,則切換成果,且未提交修改會一起帶過去,所以要注意!
      • 如果有沖突,則會報錯,提示先提交或隱藏,關于隱藏可查看后續章節內容“stash”。

      7.4、合并merge&沖突

      把兩個分支的修改內容合并到一起,常用的合并指令git merge [branch],將分支[branch]合并到當前分支。根據要合并的內容的不同,具體合并過程就會有多種情況。

      image

      ??快速合并(Fast forward)

      如下圖,master分支么有任何提交,“git merge dev”合并分支devmaster,此時合并速度就非???,直接移動master的“指針”引用到dev即可。這就是快速合并(Fast forward),不會產生新的提交。

      image

      • 合并devmaster,注意要先切換到master分支,然后執行git merge dev,把dev合并到當前分支。

      ??強制不用快速合并git merge --no-ff -m "merge with no-ff" dev,參數--no-ff不啟用快速合并,會產生一個新的合并提交記錄。

      ??普通合并

      如果master有變更,存在分支交叉,則會把兩邊的變更合并成一個提交。

      • 如果兩邊變更的文件不同,沒有什么沖突,就自動合并了。
      • 如果有修改同一個文件,則會存在沖突,到底該采用哪邊的,程序無法判斷,就換產生沖突。沖突內容需要人工修改后再重新提交,才能完成最終的合并。

      image

      上圖中,創建dev分支后,兩個分支都有修改提交,因此兩個分支就不在一條順序線上了,此時合并devmaster就得把他們的修改進行合并操作了。

      • v5、v7共同祖先是v4,從這里開始分叉。
      • Git 會用兩個分支的末端v6v8以及它們的共同祖先v4進行三方合并計算。合并之后會生成一個新(和并)提交v9。
      • 合并提交v9就有兩個祖先v6、v8。

      ??處理沖突<<<<<<< HEAD

      在有沖突的文件中,<<<<<<< HEAD開頭的內容就表示是有沖突的部分,需要人工處理,可以借助一些第三方的對比工具。人工處理完畢后,完成合并提交,才最終完成此次合并。=======分割線上方是當前分支的內容,下方是被合并分支的變更內容。

      image.png

      7.5、變基rebase

      把兩個分支的修改內容合并到一起的辦法有兩種:mergerebase,作用都是一樣的,區別是rebase的提交歷史更簡潔,干掉了分叉,merge的提交歷史更完整。

      image

      • dev上執行“git rebase master”變基,將dev分支上分叉的v7、v8生成補丁,然后在master分支上應用補丁,產生新的v7'、v8'新的提交。
      • 然后回到master分支,完成合并git merge dev,此時的合并就是快速合并了。
      • 最終的提交記錄就沒有分叉了。
      $ git rebase master
      $ git checkout master
      $ git merge dev
      

      08、標簽管理

      標簽(Tags)指的是某個分支某個特定時間點的狀態,是對某一個提交記錄的的固定“指針”引用。一經創建,不可移動,存儲在工作區根目錄下.git\refs\tags??梢岳斫鉃槟骋淮翁峤唬ň幪枺┑膭e名,常用來標記版本。所以發布時,一般都會打一個版本標簽,作為該版本的快照,指向對應提交commit。

      當項目達到一個關鍵節點,希望永遠記住那個特別的提交快照,你可以使用 git tag 給它打上標簽。比如我們今天終于完成了V1.1版本的開發、測試,并成功上線了,那就可給今天最后這個提交打一個標簽“V1.1”,便于版本管理。

      默認標簽是打在最新提交的commit上的,如果希望在指定的提交上打標簽則帶上提交編號(commit id):git tag v0.9 f52c633

      image

      指令 描述
      git tag 查看標簽列表
      git tag -l 'a*' 查看名稱是“a”開頭的標簽列表,帶查詢參數
      git show [tagname] 查看標簽信息
      git tag [tagname] 創建一個標簽,默認標簽是打在最新提交的commit上的
      git tag [tagname] [commit id] 新建一個tag在指定commit上
      git tag -a v5.1 -m'v5.1版本' 創建標簽v5.1.1039,-a指定標簽名,-m指定說明文字
      git tag -d [tagname] 刪除本地標簽
      git checkout v5.1.1039 切換標簽,同切換分支
      git push [remote] v5.1 推送標簽,標簽不會默認隨代碼推送推送到服務端
      git push [remote] --tags 提交所有tag

      如果要推送某個標簽到遠程,使用命令git push origin [tagname],或者,一次性推送全部到遠程:git push origin --tags

      ??注意:標簽總是和某個commit掛鉤。如果這個commit既出現在master分支,又出現在dev分支,那么在這兩個分支上都可以看到這個標簽。

      # tag
      $ git tag -a 'v1' -m'v1版本'
      $ cat .git/refs/tags/v1
      a2e2c9caea35e176cf61e96ad9d5a929cfb82461
      
      # 查看標簽列表
      $ git tag
      v1
      

      09、后悔藥-怎么撤銷變更?

      發現寫錯了要回退怎么辦?看看下面幾種后悔指令吧!

      • ?還沒提交的怎么撤銷? —— checkout、reset
        • 還未提交的修改(工作區、暫存區)不想要了,用簽出指令(checkout)進行撤銷清除。
        • 或者用checkout的新版回滾指令reset。
      • ?已提交但么有push的提交如何撤銷?—— reset、revert
      • ?已push的提交如何撤銷?—— 同上,先本地撤銷,然后強制推送git push origin -f,??注意慎用! 記得先pull獲取更新。

      image

      9.1、后悔指令??

      指令 描述
      git checkout . 撤銷工作區的(未暫存)修改,把暫存區恢復到工作區。不影響暫存區,如果沒暫存,則撤銷所有工作區修改
      git checkout [file] 同上,file指定文件
      git checkout HEAD . 撤銷工作區、暫存區的修改,用HEAD指向的當前分支最新版本替換工作區、暫存區
      git checkout HEAD [file] 同上,file指定文件
      git reset 撤銷暫存區狀態,同git reset HEAD,不影響工作區
      git reset HEAD [file] 同上,指定文件file,HEAD可省略
      git reset [commit] 回退到指定版本,清空暫存區,不影響工作區。工作區需要手動git checkout簽出
      git reset --soft [commit] 移動分支master、HEAD到指定的版本,不影響暫存區、工作區,需手動git checkout簽出更新
      git reset --hard HEAD 撤銷工作區、暫存區的修改,用當前最新版
      git reset --hard HEAD~ 回退到上一個版本,并重置工作區、暫存區內容。
      git reset --hard [commit] 回退到指定版本,并重置工作區、暫存區內容。
      git revert[commit] 撤銷一個提交,會用一個新的提交(原提交的逆向操作)來完成撤銷操作,如果已push則重新push即可
      • git checkout .、git checkout [file] 會清除工作區中未添加到暫存區的修改,用暫存區內容替換工作區。
      • git checkout HEAD .、 git checkout HEAD [file] 會清除工作區、暫存區的修改,用HEAD指向的當前分支最新版本替換暫存區、工作區。
      # 只撤銷工作區的修改(未暫存)
      $ git checkout .
      Updated 1 path from the index
      
      # 撤銷工作區、暫存區的修改
      $ git checkout HEAD .
      Updated 1 path from f951a96
      

      9.2、回退版本reset

      reset是專門用來撤銷修改、回退版本的指令,支持的場景比較多,多種撤銷姿勢,所以參數組合也比較多。簡單理解就是移動master分支、HEAD的“指針”地址,理解這一點就基本掌握reset了。

      如下圖:

      • 回退版本git reset --hard v4 或 git reset --hard HEAD~2,master、HEAD會指向v4提交,v5、v6就被廢棄了。
      • 也可以重新恢復到v6版本:git reset --hard v6,就是移動master、HEAD的“指針”地址。

      image

      reset有三種模式,對應三種參數:mixed(默認模式)、soft、hard。三種參數的主要區別就是對工作區、暫存區的操作不同。

      • mixed為默認模式,參數可以省略。
      • 只有hard模式會重置工作區、暫存區,一般用這個模式會多一點。

      image

      模式名稱\ 描述 HEAD的位置 暫存區 工作區
      soft 回退到某一個版本,工作區不變,需手動git checkout 修改 不修改 不修改
      mixed(默認) 撤銷暫存區狀態,不影響工作區,需手動git checkout 修改 修改 不修改
      hard 重置未提交修改(工作區、暫存區) 修改 修改 修改

      穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本。

      git reset [--soft | --mixed | --hard] [HEAD]
      
      # 撤銷暫存區
      $ git reset
      Unstaged changes after reset:
      M       R.md
      
      # 撤銷工作區、暫存區修改
      $ git reset --hard HEAD
      
      # 回退版本庫到上一個版本,并重置工作區、暫存
      $ git reset --hard HEAD~
      
      # 回到原來的版本(恢復上一步的撤銷操作),并重置工作區、暫存
      $ git reset --hard 5f8b961
      
      # 查看所有歷史提交記錄
      $ git reflog
      ccb9937 (HEAD -> main, origin/main, origin/HEAD) HEAD@{0}: commit: 報表新增導入功能
      8f61a60 HEAD@{1}: commit: bug:修復報表導出bug
      4869ff7 HEAD@{2}: commit: 用戶報表模塊開發
      4b1028c HEAD@{3}: commit: 財務報表模塊開發完成
      

      9.3、撤銷提交revert

      安全的撤銷某一個提交記錄,基本原理就是生產一個新的提交,用原提交的逆向操作來完成撤銷操作。注意,這不同于reset,reset是回退版本,revert只是用于撤銷某一次歷史提交,操作是比較安全的。

      image

      如上圖:

      • 想撤銷v4的修改,執行git revert v4,會產生一個新的提交v-4,是v4的逆向操作。
      • 同時更新maser、HEAD“指針”位置,以及工作區內容。
      • 如果已push則重新push即可。
      # revert撤銷指定的提交,“-m”附加說明
      $ git revert 41ea42 -m'撤銷對***的修改'
      [main 967560f] Revert "123"
                                  1 file changed, 1 deletion(-)
      

      9.4、checkout/reset/revert總結

      標題 \ 指令 checkout reset revert
      主要作用(撤銷) 撤銷工作區、暫存區未提交修改 回退版本,重置工作區、暫存區 撤銷某一次提交
      撤銷工作區 git checkout [file] git reset HEAD [file]
      撤銷工作區、暫存區 git checkout HEAD [file] git reset --hard HEAD [file]
      回退版本 git reset --hard [commit]
      安全性 只針對未提交修改,安全 如回退了已push提交,不安全 安全

      可看出reset完全可以替代checkout來執行撤銷、回退操作,reset本來也是專門用來干這個事情的,可以拋棄checkout了(撤銷的時候)。


      10、工作中的Git實踐

      10.1、Git flow

      Git flow(Git工作流程)是指軟件項目中的一種Git分支管理模型,經過了大量的實踐和優化,被認為是現代敏捷軟件開發和DevOps(開發、技術運營和質量保障三者的交集)的最佳實踐。Git flow主要流程及關鍵分支:原圖地址-processon

      image.png

      ?主分支:master,穩定版本代碼分支,對外可以隨時編譯發布的分支,不允許直接Push代碼,只能請求合并(pull request),且只接受hotfix、release分支的代碼合并。

      ?熱修復分支:hotfix,針對線上緊急問題、bug修復的代碼分支,修復完后合并到主分支、開發分支。

      • ① 切換到hotfix分支,從master更新代碼;
      • ② 修復bug;
      • ③ 合并代碼到dev分支,在本地Git中操作即可;
      • ④ 合并代碼到master分支。

      image.png

      ?發版分支:release,版本發布分支,用于迭代版本發布。迭代開發完成后,合并dev代碼到release,在release分支上編譯發布版本,以及修改bug(定時同步bug修改到dev分支)。測試完成后此版本可以作為發版使用,然后把穩定的代碼push到master分支,并打上版本標簽。

      ?開發分支:dev,開發版本分支,針對迭代任務開發的分支,日常開發原則上都在此分支上面,迭代完成后合并到release分支,開發、發版兩不誤。

      image.png

      ?其他開發分支:dev-xxx,開發人員可以針對模塊自己創建本地分支,開發完成后合并到dev開發分支,然后刪除本地分支。

      10.2、金屋藏嬌stash

      當你正在dev分支開發一個功能時,代碼寫了一半,突然有一個線上的bug急需要馬上修改。dev分支Bug沒寫完,不方便提交,就不能切換到主分支去修復線上bug。Git提供一個stash功能,可以把當前工作區、暫存區 未提交的內容“隱藏”起來,就像什么都沒發生一樣。

      # 有未提交修改,切換分支時報錯
      $ git checkout dev
      error: Your local changes to the following files would be overwritten by checkout:
              README.md
      Please commit your changes or stash them before you switch branches.
      Aborting
      
      # 隱藏
      $ git stash
      Saved working directory and index state WIP on main: 2bc012c s
      
      # 查看被隱藏的內容
      $ git stash list
      stash@{0}: WIP on main: 2bc012c s
      
      # 比較一下,什么都沒有,一切都沒有發生過!
      $ git diff
      
      # 去其他分支修改bug,修復完成回到當前分支,恢復工作區
      $ git stash pop
      

      在上面示例中,有未提交修改,切換分支時報錯。錯誤提示信息很明確了,commit提交或stash隱藏:Please commit your changes or stash them before you switch branches.

      ?? 如果切換分支時,未提交修改的內容沒有沖突,是可以成功切換的,未提交修改會被帶過去。

      指令 描述
      git stash 把未提交內容隱藏起來,包括未暫存、已暫存。 等以后恢復現場后繼續工作
      git stash list 查看所有被隱藏的內容列表
      git stash pop 恢復被隱藏的內容,同時刪除隱藏記錄
      git stash save "message" git stash,可以備注說明message
      git stash apply 恢復被隱藏的文件,但是隱藏記錄不刪除
      git stash drop 刪除隱藏記錄

      ??當然這里先提交到本地也是可以的,只是提交不是一個完整的功能代碼,而是殘缺的一部分,影響也不大。

      揀選提交cherry-pick

      當有一個緊急bug,在dev上修復完,我們需要把dev上的這個bug修復所做的修改“復制”到master分支,但不想把整個dev合并過去。為了方便操作,Git專門提供了一個cherry-pick命令,讓我們能復制一個特定的提交到當前分支,而不管這個提交在哪個分支。

      image

      如上圖,操作過程相當于將該提交導出為補丁文件,然后在當前HEAD上重放,形成無論內容還是提交說明都一致的提交。

      • 希望把dev分支上的v7提交的內容合并到master,但不需要其他的內容。
      • master分支上執行指令git cherry-pick v7,會產生一個新的v7'提交,內容和v7相同。
      • 同時更新master、HEAD,以及工作區。
      # 選擇一個commit,合并進當前分支
      $ git cherry-pick [commit]
      

      參考資料


      ??版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請注明出處!原文編輯地址-語雀

      posted @ 2023-02-01 11:47  安木夕  閱讀(10804)  評論(32編輯  收藏  舉報
      欧洲黄色网页链接入口,免费A级毛片无码无遮挡久久影院,a免费黄色网址,国产一级黄色的网站
      <optgroup id="6y7f6"><small id="6y7f6"></small></optgroup>

      <code id="6y7f6"></code>

    1. <p id="6y7f6"><tbody id="6y7f6"><ins id="6y7f6"></ins></tbody></p>
      <code id="6y7f6"><form id="6y7f6"></form></code>