Git 操作總結

1. 安裝、Git 環境配置

1.1 安裝 Git

官方版本可以在 Git 官方網站下載:打開 https://git-scm.com/download/win,選擇相應版本即可。

Git 安裝完成后,可以在開始菜單中看到 Git 的三個啟動圖標(Git Bash、Git CMD、Git GUI)。Git Bash 是 Git 配套的一個控制臺,在空白處右鍵,點擊 Open Git Bash here 即可開始使用 Git。

?

1.2 Git 環境配置:通過 git config 命令配置用戶信息

安裝完 Git 之后,要做的第一件事就是設置你的用戶名和郵件地址。 這一點很重要,因為每一個 Git 提交都會使用這些信息,它們會寫入到你的每一次提交中,不可更改。

1.2.1 配置用戶名和郵件地址

git config --global user.name "abigailqin"

git config --global user.email abigailqin@csdn.net

注意:git config --global user.name "xxxx",要有雙引號。如果使用了 --global 選項,那么該命令只需要運行一次,因為之后無論你在該系統上做任何事情, Git 都會使用那些信息。

如果想針對特定項目使用不同的用戶名稱與郵件地址時,可以在那個項目目錄下運行沒有 --global 選項的命令來配置。

1.2.2 查看配置

(1)使用 git config --list 命令列出 Git 當前能找到的所有配置

(2)使用 git config <key> 檢查 Git 的某一項配置。

1.3 SSH Key

SSH Key 是一種用于在 Git 版本控制系統中進行安全身份驗證的機制。它是一對密鑰,包括公鑰和私鑰,公鑰存儲在 Git 服務器上,而私鑰則存儲在用戶的本地計算機上。Git SSH Key 通過使用加密技術,確保只有具有正確私鑰的用戶才能訪問 Git 倉庫。SSH Key 允許用戶通過 SSH 連接到 Git 服務器,而不需要輸入密碼,這種身份驗證方式比傳統的基于用戶名和密碼的身份驗證更加安全和可靠。

向 Git 服務器提供 SSH 公鑰的過程在所有操作系統上都是相似的:首先,需要確認自己是否已經擁有密鑰。 默認情況下,用戶的 SSH 密鑰存儲在其 ~/.ssh 目錄下,進入該目錄并列出其中內容,便可以快速確認自己是否已擁有密鑰。

我們需要尋找一對以 id_dsa 或 id_rsa 命名的文件,其中一個帶有 .pub 擴展名。 .pub 文件是公鑰,另 一個則是私鑰。 如果找不到這樣的文件(或者根本沒有 .ssh 目錄),可以通過運行 ssh-keygen 程序來創建它們。首先 ssh-keygen 會確認密鑰的存儲位置(默認是 .ssh/id_rsa),然后它會要求你輸入兩次密鑰口令,如果你不想在使用密鑰時輸入口令,將其留空即可。

現在,進行了上述操作的用戶需要將各自的公鑰發送給?Git 服務器管理員(假設服務器正在使用基于公鑰的 SSH 驗證設置),復制?.pub 文件內容,并將其通過郵件發送即可。

1.4?定制 Git 環境

Git 自帶 git config 工具來幫助設置控制 Git 外觀和行為的配置變量。

這些 Git 配置變量存儲在三個不同的位置:

1. /etc/gitconfig 文件(Git 安裝目錄): 包含系統上每一個用戶及他們倉庫的通用配置。 如果在執行 git config 時帶上 --system 選項,那么它就會讀寫該文件中的配置變量?(由于它是系統配置文件,因此你需要管理員或超級用戶權限來修改它)。

2. ~/.gitconfig 或 ~/.config/git/config 文件:只針對當前用戶。 可以傳遞 --global 選項讓 Git 讀寫此文件,這會對你系統上所有的倉庫生效。

3. 當前使用倉庫的 Git 目錄中的 config 文件(即 .git/config):針對該倉庫。 可以傳遞 --local 選項讓 Git 強制讀寫此文件,雖然默認情況下用的就是它(當然,你需要進入這個 Git 倉庫中才能讓該選項生效)。

每一個級別會覆蓋上一級別的配置,所以 .git/config 的配置變量會覆蓋 /etc/gitconfig 中的配置變量。

使用?git config --list --show-origin?查看所有的配置以及它們所在的文件。

1.3.1?忽略文件 .gitignore

在 Git 工作區的根目錄下創建一個特殊的 .gitignore 文件,然后把要忽略的文件名填進去,Git 在每次進行提交的時候就會自動忽略這些文件。我們一般不需要從頭開始編輯?.gitignore 文件,已經有各種現成的種配置文件,只需要組合一下就可以使用了。所有配置文件可以直接在線瀏覽:https://gitcode.net/codechina/gitignore

忽略文件的原則:

  • 忽略操作系統自動生成的文件,比如縮略圖等;
  • 忽略編譯生成的中間文件、可執行文件等,也就是如果一個文件是通過另一個文件自動生成的,那自動生成的文件就沒必要放進版本庫,比如Java編譯產生的.class文件;
  • 忽略帶有敏感信息的配置文件,比如存放口令的配置文件。

假設你在 Windows 下進行 Python 開發:

Windows 會自動在有圖片的目錄下生成隱藏的縮略圖文件,如果有自定義目錄,目錄下會有 Desktop.ini 文件,需要忽略上述 Windows 自動生成的垃圾文件;此外,還需忽略 Python 編譯產生的.pyc、.pyo、dist等文件或目錄;再加上你自己定義的文件,得到一個完整的 .gitignore 文件(內容如下),最后一步就是把 .gitignore 也提交到 Git,就完成了。

<.gitignore>

# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build# My configurations:
db.ini
deploy_key_rsa

1.3.2?強制添加被忽略文件 git?add -f

有時候可能想添加一個文件到 Git,但發現添加不了,因為這個文件被 .gitignore 忽略了。如果你確實想添加該文件,可以用 -f 強制添加到 Git

$ git add -f App.class

盡管可以用 git add -f 強制將此文件添加進去,但建議你添加一條例外規則:把指定文件排除在 .gitignore 規則外,寫法是:?!+文件名

<.gitignore>

# 排除所有 .class 文件
*.class# 不排除 .App.class 文件
!App.class

如果覺得添加不了是 .gitignore 寫得有問題,需要找出來到底哪個規則寫錯了,可以用 git check-ignore 命令檢查。

$ git check-ignore -v App.class
.gitignore:3:*.class App.class# 返回結果說明:.gitignore 的第3行規則忽略了該文件,因此修訂第3行規則即可。

1.3.3?配置別名 git config --global alias.xx yyyy?

使用 Git 命令時,可以通過配置別名的方式簡化命令。比如,給?git status 命令配置一個別名: git st,輸入 git st 就比輸入 git status 簡單方便很多。下述這行命令就是告訴 Git,以后 st 就表示 status,--global參數是全局參數,表示這個命令在這臺電腦的所有 Git 倉庫下都可以使用。

$ git config --global alias.st status

示例-1:用 ci 表示 commit

$ git config --global alias.ci commit$ git ci -m "sth."

示例-2:用 last 表示 log -1,git last 表示 git log -1,即顯示最近一次的提交

$ git config --global alias.last 'log -1'$ git last

示例-3:用 unstage 表示?reset HEAD,git unstage <file> 即為 git reset HEAD <file>,撤銷暫存區的修改。?

1.5?獲取幫助

如果在使用 Git 時需要獲取幫助,可以使用 help 命令找到 Git 命令的使用手冊:

$ git help <verb>
$ git <verb> --help

例如,要想獲得 config 命令的手冊,執行 git help config 命令或?git config --help 命令后將跳轉到使用手冊對應頁:

2. Git 倉庫

2.1 工作目錄(working tree\working directory)、暫存區域(staging area\index)和 Git 倉庫(repository\git repository)

Git 項目有三個工作區域的概念:工作目錄、暫存區域和 Git 倉庫。

  1. Git 倉庫目錄是 Git 用來保存項目的元數據和對象數據庫的地方。 這是 Git 中最重要的部分,從其它計算機克隆倉庫時,拷貝的就是這里的數據。
  2. 工作目錄是對項目的某個版本獨立提取出來的內容,是你在電腦里能看到的目錄。 這些從 Git 倉庫的壓縮數據庫中提取出來的文件,放在磁盤上供你使用或修改。
  3. 暫存區域是一個文件,保存了下次將提交的文件列表信息,一般在 Git 倉庫目錄中,有時候也被稱作 ‘索引’(index),不過一般說法還是叫暫存區域(staging area)。

基本的 Git 工作流程如下:

  1. 在工作目錄中修改文件。
  2. 暫存文件,將文件的快照放入暫存區域。
  3. 提交更新,找到暫存區域的文件,將快照永久性存儲到 Git 倉庫目錄。

如果 Git 目錄中保存著的特定版本文件,就屬于已提交狀態。 如果作了修改并已放入暫存區域,就屬于已暫存狀態。 如果自上次取出后,作了修改但還沒有放到暫存區域,就是已修改狀態

在你的工作目錄下的每一個文件都不外乎這兩種狀態:已跟蹤或未跟蹤。 已跟蹤的文件是指那些被納入了版本控制的文件,在上一次快照中有它們的記錄,在工作一段時間后,它們的狀態可能處于未修改,已修改或已放入暫存區。 工作目錄中除已跟蹤文件以外的所有其它文件都屬于未跟蹤文件,它們既不存在于上次快照的記錄中,也沒有放入暫存區。 初次克隆某個倉庫的時候,工作目錄中的所有文件都屬于已跟蹤文件,并處于未修改狀態。

2.2 使用 git init 在現有目錄中初始化倉庫

git init 用于在當前目錄下初始化一個新的 Git 倉庫。初始化后,會在當前目錄下創建一個名為 .git的隱藏文件夾,其中包含了 Git 倉庫的所有元數據和歷史記錄。執行該命令后,當前目錄下的所有文件和子目錄都會被納入 Git 的版本控制中,你可以開始添加、修改和提交文件到 Git 倉庫。

2.3 使用 git clone?克隆現有的倉庫

語法:git clone <遠程倉庫地址>,例如,如果要將 GitHub 上的一個倉庫復制到本地,可以使用以下命令:git clone https://github.com/username/repo.git,其中,username?是 GitHub 用戶名,repo?是倉庫名稱。

3. 基礎操作

3.1 檢查文件狀態 git status

要查看哪些文件處于什么狀態,可以用 git status 命令。

該命令顯示了當前所在分支(當前的分支名是 master,這是默認的分支名),并告訴你當前工作目錄中哪些文件被修改了、哪些文件被添加或刪除了、哪些文件已經被暫存了等等。

git status 命令的輸出十分詳細,但其顯示結果有些繁瑣。 可以使用 git status -s 命令或 git status --short 命令,得到更為緊湊的格式輸出,示例:

  1. 新添加的未跟蹤文件前面有 ?? 標記;
  2. 新添加到暫存區中的文件前面有 A 標記;
  3. 修改過的文件前面有 M 標記,M 有兩個可以出現的位置,出現在右邊的 M 表示該文件在工作區被修改了且沒放入暫存區,出現在靠左邊的 M 表示該文件在工作區被修改了并放入了暫存區,MM表示此文件在工作區被修改并提交到暫存區后又在工作區中被修改了,所以在暫存區和工作區都有該文件被修改了的記錄。

3.2 跟蹤新文件、暫存已修改文件:git add

git add 是一個多功能命令:可以用它開始跟蹤新文件,或者把已跟蹤的文件放到暫存區,還能用于合并時把有沖突的文件標記為已解決狀態等。 將這個命令理解為 “添加內容到下一次提交中” 而不是 “將一個文件添加到項目中” 要更加合適。

3.2.1 跟蹤新文件 git add <pathspec>…??

git add 命令使用文件或目錄的路徑作為參數;如果參數是目錄的路徑,該命令將遞歸地跟蹤該目錄下的所有文件。使用 add 后可以再用 git status 查看一下文件狀態,只要在 Changes to be committed 這行下面的,就說明是已暫存狀態。

?可以在 git add?命令后面跟上多個文件名,用空格隔開。

3.2.2 暫存已修改的文件 git add <pathspec>…??

出現在 Changes not staged for commit 下面的文件,已跟蹤但內容發生了變化,還沒有放到暫存區,需要運行 git add 命令暫存這次更新。

如果在運行了 git add 之后又作了修改,需要重新運行 git add 把最新版本重新暫存起來。

3.3 撤銷工作區修改或撤銷暫存操作 git restore <pathspec>…??

3.3.1 撤銷工作區未暫存的修改:git restore <pathspec>…?

git restore <pathspec>...?可以將工作區指定的文件或目錄恢復成和暫存區一致的狀態。如果指定的文件或目錄在暫存區中已經有了修改,那么這些修改也會被覆蓋掉,恢復成暫存區中的版本,<pathspec>…??表示需要恢復的文件或目錄。使用 git restore?命令會直接覆蓋當前工作區的文件,因此請謹慎使用。

假如你在工作區修改了 temp.txt 文件的內容,但還沒有將修改暫存到暫存區,如果想撤銷修改,可以使用 git restore 命令:

如果想要將文件或目錄恢復到指定的提交狀態,可以使用 git restore?命令加上 --source 參數:

git restore --source=<commit> <pathspec>…?

3.3.2 保留工作區修改撤銷暫存(可以用 git reset 實現一樣的功能):git restore --staged?<pathspec>…?

git restore --staged?<pathspec>…? 命令可將暫存區指定的文件恢復到最新的提交狀態(HEAD),撤銷已暫存但未提交的更改,但不會不修改工作區文件內容

在 Git 中,用 HEAD 表示當前倉庫版本,也就是最新的提交,上一個版本是 HEAD^,上上一個版本是 HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成 HEAD~100。

使用 --source 將暫存區恢復到指定的提交狀態,不改動工作區

git restore --source=<commit> --staged <pathspec>…?

下面的場景中,先對兩個文件使用 mv 命令執行重命名操作,并把兩次操作記錄到暫存區。

如果想把這兩次操作分兩次提交,想撤銷暫存區中的 renamed temp2.txt -> temp.txt,可使用 --staged,恢復暫存區內容。HEAD 對應的暫存區中沒有 temp.txt,執行 restore temp.txt 命令后 temp.txt 變成 untracked;HEAD 對應的暫存區中存在?temp2.txt 文件,但工作區目錄刪除了此文件,因此執行 restore temp2.txt 命令后后顯示 deleted temp2.txt 未加入暫存區。

3.3.3 撤銷暫存以及工作區修改(可以用 git reset --hard HEAD 實現一樣的功能):git restore --staged --worktree <pathspec>…? 回到最近一次提交狀態

3.3.4 使用 git reset 撤銷工作區修改或撤銷暫存

參考 3.7 & 3.8?

3.3.5 使用 git checkout 恢復文件

git checkout <commit> <file> 命令會將文件恢復到最近一次提交的狀態,且會丟失未提交的修改。

3.4?刪除文件 git rm?

3.4.1 刪除文件 git rm?<pathspec>…?

使用 git rm 命令從已跟蹤文件清單中移除文件(確切地說,是從暫存區域移除),并連帶從工作目錄中刪除指定的文件,執行 git rm 后再執行 git commit,即可從 Git 中移除文件。

如果只是簡單地從工作目錄中手工刪除文件,運行 git status 時就會在 “Changes not staged for commit” 部分(也就是未暫存清單)看到:"deleted: filename",運行 git rm 記錄此次移除文件的操作,下一次執行 git commit 后,該文件就不再納入版本管理了。

3.4.2 強制刪除文件 git rm -f?<pathspec>…?

如果文件沒有被添加到 Git 倉庫中,git rm 命令會報錯;如果你嘗試刪除一個修改過并且已經把修改放到暫存區的文件,git rm?命令會提示你需要先將修改提交到 Git 倉庫中。

如果一定要刪除之前修改過并且已經放到暫存區的文件,或者倉庫中不存在的文件,要用強制刪除選項 -f(force 的首字母)。git rm -f?命令可以強制刪除已經被 Git 跟蹤的文件,即使該文件被修改過并且沒有被提交到 Git 倉庫中,使用該命令時需要小心,它會永久刪除文件,無法恢復。

3.4.3 從暫存區和 Git 倉庫中刪除但本地不刪除?git rm -cached?<pathspec>…?

當想把文件從 Git 倉庫中刪除(亦從暫存區域移除),但仍然希望保留在當前工作目錄中時,使用 git rm --cached <pathspec>…? 。 換句話說,你想讓文件保留在磁盤,但是并不想讓 Git 繼續跟蹤。

$ git rm log/\*.log
# 表示刪除 log/ 目錄下擴展名為 .log 的所有文件
# 星號 * 之前的反斜杠 \,這是 Git 自己的文件模式擴展匹配方式。$ git rm \*~、
# 表示刪除以 ~ 結尾的所有文件。

3.5?移動文件?git mv <source> <destination>?

$ git mv README.md README

命令 git mv README.md README,將對文件改名,運行此命令相當于運行了下面三條命令:

$ mv README.md README
$ git rm README.md
$ git add README

3.6?比較文件內容 git diff

比較工作目錄中的文件與最新提交之間的差異:git diff

比較指定文件在工作目錄和最新提交之間的差異:git diff <file>

比較工作目錄中的文件與指定的提交之間的差異:git diff <commit>

比較兩個提交之間的差異:git diff <commit1> <commit2>

比較指定文件在兩個提交之間的差異:git diff <commit1> <commit2> <file>

比較兩個分支之間的差異:git diff <branch1> <branch2>

比較指定文件在兩個分支之間的差異:git diff <branch1> <branch2> <file>

?3.7?提交更新 git commit

3.7.1 提交更新-編輯器輸入提交信息?git commit?

如果暫存區域已經準備妥當可以提交了,就可以使用 git commit 命令將修改提交到倉庫。 請一定要確認還有什么修改過的或新建的文件還沒有 git add 過,否則提交的時候不會記錄這些還沒暫存起來的變化,這些修改過的文件只保留在本地磁盤。 所以,每次準備提交前,先用 git status 看下,是不是都已暫存起來了, 然后再運行提交命令 git commit。

這種方式將會啟動文本編輯器以便輸入本次提交的說明。 (默認會啟用 shell 的環境變量 EDITOR 所指定的軟件, 一般都是 vim 或 emacs。編輯器顯示的內容示例:

第一行是空行,供你輸入提交說明。提交消息的注釋行里包含最后一次運行 git status 的輸出,其實完全可以去掉這些注釋行,不過留著也沒關系,多少能幫你回想起這次更新的內容有哪些。 如果想要更詳細的,關于修改了哪些內容的提示,可以用 -v 選項,這會將你所做的改變的 diff 輸出放到編輯器中,使你知道本次提交具體做了哪些修改。退出編輯器時,Git 會丟掉注釋行,用你輸入提交附帶信息生成一次提交。

注:Vim 使用

正常模式 (:)-> 命令模式(內置命令如 w wq)

正常模式 (i)-> 插入模式(編輯功能)(Esc)-> 正常模式

先在鍵盤點擊 i 按鍵,進入插入模式;然后在首行填寫提交描述,完成后點擊?Esc 退出插入模式;接下來按 : 進入命令模式,輸入 wq 保存并退出。

3.7.2 提交更新-直接輸入提交信息 git commit -m?<msg>

可以在 commit 命令后添加 -m 選項,將提交信息與命令放在同一行,這樣就不必通過 vim 添加提交信息了。

如果你只需要提交一些小的更改,并且提交信息比較簡單,可以使用 git commit -m 命令;如果你需要提交一些比較大的更改,并且需要詳細描述這些更改的內容,那么可以使用 git commit 命令,并在編輯器中輸入詳細的提交信息。

3.7.3 重新提交 git commit --amend -m <msg>?

如果在提交完才發現漏掉了幾個文件沒有添加,或者提交信息寫錯了,可以運行帶有 --amend 選項的提交命令嘗試重新提交(最終將只有一個提交)。

修補提交最明顯的價值是,可以稍微改進你最后的提交,而不會讓 “啊,忘了添加一個文件”或者 “小修補,修正筆誤” 這種提交信息弄亂你的倉庫歷史。

例如,你提交后發現忘記了暫存某些需要的修改,可以像下面這樣操作:

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend -m 'initial commit with supplements'

文本編輯器啟動后,可以看到之前的提交信息, 編輯后保存會覆蓋原來的提交信息。

3.7.4 撤銷提交 git reset [--soft/mixed/hard] [<commit>]?

參考 3.7、3.8

3.7.5 為提交打標簽 git tag

標簽可以用來標識特定的提交或版本,方便用戶在未來快速找到這個提交或版本。Git 主要有兩種類型的標簽:輕量標簽(lightweight)與附注標簽(annotated)。

輕量級標簽只是一個指向特定提交的引用,它不包含任何其他元數據,因此比帶注釋的標簽(annotated tag)更輕量級,通常用于臨時標記某個特定的提交。附注標簽是存儲在 Git 數據庫中的一個完整對象,是可以被校驗的,其中包含打標簽者的名字、電子郵件地址、日期時間以及標簽信息。 通常建議創建附注標簽,這樣你可以擁有以上所有信息;但如果你只是想用一個臨時的標簽,或者因為某些原因不想保存那些信息,用輕量標簽也是可以的。

查看標簽和刪除標簽

使用 git tag 查看標簽,這個命令以字母順序列出標簽,注意,標簽不是按時間順序列出,而是按字母排序的;使用 git show <tagname> 查看指定標簽的詳細信息,包括標簽的提交信息和提交內容;使用 git tag -d <tagname> 刪除指定的標簽。

創建標簽

在 Git 中創建標簽非常簡單:切換到需要打標簽的分支上,然后運行 git tag 命令即可。默認標簽是打在最新提交的 commit 上的。

  • 創建輕量標簽時只需要提供標簽名字,如:git tag v1.4-lw
  • 創建附注標簽需要在運行 tag 命令時指定 -a 選項,如:git tag -a v1.4 -m 'my version 1.4',-a 選項表示創建一個附注標簽;-m 選項指定了一條將會存儲在標簽中的信息,如果沒有為附注標簽指定一條信息,Git 會運行編輯器要求你輸入信息。
后期打標簽

如果想對過去的提交打標簽,可以先運行 git reflog 查看歷史提交信息,找到目標提交的校驗和(或部分校驗和),在命令末尾加上它,如:git tag -a v1.2 9fceb02。

共享標簽

默認情況下,git push 命令并不會傳送標簽到遠程倉庫服務器上。 在創建完標簽后,你必須顯式地推送標簽到共享服務器上。 這個過程就像共享遠程分支一樣,運行 git push origin [tagname]。如果標簽已經推送到遠程,要刪除遠程標簽就麻煩一點,比如,想刪除 remove 標簽,需要先從本地刪除:git tag -d remove,然后,從遠程刪除,刪除命令也是 push,但是格式如下:git push origin :refs/tags/remove

3.8?查看提交歷史 git log

3.8.1 git log

默認不用任何參數的話,git log 會按提交時間列出所有的更新,最近的更新排在最上面。 這個命令會列出每個提交的哈希值、作者的名字和電子郵件地址、提交時間以及提交說明。

3.8.2 git log --oneline

--oneline:將每個提交壓縮為一行,是?"--pretty=oneline --abbrev-commit" 的簡寫形式。

3.8.3 其他常用選項(-p、-n、--stat、--pretty、--graph)

-p 選項:用來顯示每次提交的內容差異。

-(n) 僅顯示最近的 n 條提交。

--stat 選項:查看每次提交的簡略的統計信息。--stat 選項在每次提交的下面列出所有被修改過的文件、有多少文件被修改了以及被修改過 的文件的哪些行被移除或是添加了。 在每次提交的最后有一個總結。

--pretty:指定使用不同于默認格式的方式展示提交歷史。

--pretty 選項有 一些內建的子選項可供使用,比如?oneline 表示將每個提交放在一行顯示,格式為 <hash> <title-line>;format:<format-string>?定制要顯示的記錄格式(如 %h 代表提交的簡短哈希值,%s 代表提交說明消息,%an 代表作者名字,%cn 代表提交者名字,%cd 代表提交日期等);還有 short、medium、full、fuller 等內置格式。

如果要將輸出保存到文件中,可以使用以下命令:
git log --pretty=format:"%H - %an: %s" > log.txt

-S:僅顯示添加或移除了某個關鍵字的提交。

可以使用命令:git log -Sfunction_name,找出添加或移除了某一個特定函數的引用的提交。

3.8.4 git reflog

git log?顯示的是提交歷史,包括每個提交的作者、提交時間、提交信息等等。它可以用于查看項目的提交歷史,了解項目的演進情況,以及查找特定提交的信息等等。

Git 會在后臺保存一個引用日志 reflog,每當你的 HEAD 所指向的位置發生了變化,Git 就會將這個信息存儲到引用日志這個歷史記錄里。 通過這些數據,你可以很方便地獲取之前的提交歷史,使用 git reflog 來查看引用日志。

git reflog 顯示的是 Git 引用的歷史,包括分支、標簽、HEAD 等等。它記錄了 Git 引用的變更歷史,可以用于恢復誤刪的分支、標簽等引用,或者查找誤操作的歷史記錄等等。

3.9?撤銷提交 git reset

git reset 可用于:

  1. 取消暫存,不影響工作區內容,對應下圖 SYNOPSIS 1~3 語句。
  2. 取消提交:將當前分支的 HEAD 指針移動到指定的提交,同時可以選擇是否修改工作區和暫存區的內容。對應下圖 SYNOOSIS 第4條語句。

3.9.1 保留工作區修改撤銷暫存(tree-ish 默認為 HEAD,即最近一次的提交)

應用場景:假設你對項目中的 frotz.c 文件做了一些修改,已經改好了,接下來需要修改其他文件,你不想在運行 git diff 時看到關于 frotz.c 的內容,這會分散你的注意力,所以你使用 add 命令把這部分修改暫存到暫存區。

這時有人告訴你其他項目成員做了一些有價值的修改,建議你拉取最新項目。不過你現在已經 ‘弄臟了’ 暫存區,即你當前的暫存區內容與 HEAD 不匹配(執行 git pull 之前,需要先將暫存區和 HEAD 同步,否則會出現沖突),而且你知道將要進行的 pull 操作不會改變 frotz.c 文件,因此你可以考慮先恢復 frotz.c 文件在暫存區的狀態(撤銷之前的暫存操作,但保留工作區文件的改動),然后再pull、merge。

?git reset 也可以僅對一個文件撤銷暫存操作:

3.9.2 撤銷提交(commit 默認為 HEAD,即最近一次的提交)

-soft僅撤銷提交,不撤銷修改。將 HEAD 指針移動到指定的提交,并將暫存區和工作區的修改保留下來,因此可以直接重新提交。
--mixed撤銷提交和暫存區的修改,但不撤銷工作區的修改。將 HEAD 指針移動到指定的提交,并將暫存區的修改撤銷,但不影響工作區的修改,需要手動重新標記為暫存后再次提交。
--hard徹底撤銷提交和修改,回到指定提交的狀態。將 HEAD 指針、暫存區和工作區都移動到指定的提交,所有修改都會被撤銷,慎用。
--merge撤銷合并提交,回到合并前的狀態。撤銷合并提交,回到合并前的狀態,需要指定要回到的提交。
--keep撤銷提交,但保留工作區和暫存區的修改。

可以通過回退實現撤銷提交,這需要知道回到哪個版本:用 HEAD 表示當前版本,即最新的提交,上一個版本用 HEAD^ 表示,往上100個版本用?HEAD~100 表示;此外,如前所述 Git 會記錄每一次提交的信息,可通過 git reflog 查看索引值,用索引值指定要回退的版本。概括來說:

  • 索引值(前進后退都可以):使用 HEAD 或局部索引值(提交對象的簡短哈希字符串,可通過 git reflog 或 git log --pretty=oneline 查看)如:git reset --hard 49e25b6

  • ^ (只能后退):HEAD^^ 表示后退 2 步,如:git reset --hard HEAD^^
  • ~ (只能后退):HEAD~n 表示后退 n 步,如:git reset --hard HEAD~n

--hard 永久刪除(本地內容也會刪除)?

3.9.3 git restore 與 git reset

git restore:撤銷工作區中未提交的修改(從暫存區或另一個提交恢復工作區中的文件);從另一次提交中恢復暫存區或\和工作區中的文件。

git reset:撤銷已提交的修改。將 HEAD 指針和當前分支指向指定的提交,可選擇將暫存區或\和工作區恢復到該提交的狀態。

?4. 分支管理

使用分支意味著你可以把你的工作從開發主線上分離開來,以免影響開發主線。

Git 處理分支的方式可謂是難以置信的輕量,創建新分支這一操作幾乎能在瞬間完成,并且在不同分支之間的切換操作也是一樣便捷。 與許多其它版本控制系統不同,Git 鼓勵在工作流程中頻繁地使用分支與合并,哪怕一天之內進行許多次。?

4.1 分支簡介

4.1.1 文件快照

Git 并不是像其他版本控制系統一樣,把保存的信息看作是一組基本文件和每個文件隨時間逐步累積的差異,Git 更像是把數據看作是對小型文件系統的一組快照,你可以理解為每個快照都包含了代碼庫中的所有文件和目錄的完整內容。Git 對待數據更像是一個快照流,使用這些快照來跟蹤文件的歷史記錄,并允許不同版本之間進行比較和回滾。

說明:Git 的快照是通過將文件的內容轉換為一些稱為 “blob” 的二進制數據對象來實現的。Git 中的每個文件都被視為一系列 blob 對象,每個 blob 對象都包含文件的內容,當你在 Git 中提交一個更改時,Git 會將這些更改的內容轉換為新的 blob 對象,并將其存儲在 Git 數據庫中。Git 還會創建一個稱為 “tree” 的對象,該對象包含指向每個 blob 對象的指針,以及目錄結構信息。 這些 blob 和 tree 對象都可以被視為 Git 中的 “快照”,因為它們表示特定時間點的文件和目錄結構。

在你每次提交更新,或在 Git 中保存項目狀態時,Git 會對當時的全部文件制作一個快照并保存這個快照的索引。 為了高效, 如果文件沒有修改,Git 不再重新存儲該文件,而是只保留一個鏈接指向之前存儲的文件。

Git 中的絕大多數操作都只需要訪問本地文件和資源,比如,如果 Git 要瀏覽項目的歷史,它不需外連到服務器去獲取歷史,然后再顯示出來,只需直接從本地數據 庫中讀取,因此你能立即看到項目歷史。

4.1.2 驗證文件

哈希是一種算法,它將輸入的數據映射到一個固定長度的輸出,通常是一個哈希值。在計算機科學中,哈希經常用于快速查找和存儲數據。密碼學中,哈希算法可以把明文加密成密文。

哈希函數如下特點:

(1)同一個哈希算法得到的加密結果長度固定。

(2)哈希算法確定、輸入數據確定,輸出數據不變;如果哈希算法有變化,或者輸入數據變化(即便是很微小的變化),輸出數據一定有變化,而且變化很大。輸入數據的任何細微變化都會導致輸出數據的巨大變化。

(3)哈希算法不可逆,不能通過哈希值恢復出原始數據。

哈希算法可以用于驗證文件,Git 中,每個文件和每個提交都有一個唯一的校驗和,是一個 SHA-1 哈希值(一個由 40 個十六進制字符(0-9 和 a-f)組成字符串,示例:24b9da6552252987aa493b52f8696cd6d3b00373),這個校驗和是由文件內容和目錄結構計算出來的,可以用來驗證文件的完整性和一致性。Git 數據庫中保存的信息都是以文件內容的哈希值來索引,而不是文件名。

4.1.3 Git 分支管理機制

提交對象 commit:包含指向前述樹對象的指針和所有提交信息。

樹對象 tree:樹對象包含了每個文件和子目錄的名稱、類型、權限和 SHA-1 校驗和等元數據信息。當我們提交一個新版本的代碼時,Git 會將所有修改的文件和目錄打包成一個新的樹對象,并將其保存到 Git 數據庫中。

文件快照?blob 對象:當前版本的文件快照。

在 Git 中,每次提交都會生成一個校驗和,這個校驗和是由 Git 對該提交中所有文件的內容計算出來的。如果你修改了某些文件并提交了這些修改,Git 會重新計算該提交的校驗和,并將其與之前的校驗和進行比較。如果校驗和不同,Git 就會認為文件已經被修改過了,并提示你進行提交。

當你做了一些修改后再次提交,這次產生的提交對象會包含一個指向上次提交對象(父對象)的指針。

Git 的分支本質上是指向提交對象可變指針。 Git 的默認分支名字是 master。 在多次提交操作之 后,你其實已經有一個指向最后那個提交對象的 master 分支,它會在每次的提交操作中自動向前移動。

Git 的 master?分支并不是一個特殊分支。 它就跟其它分支完全沒有區別。 之所以幾乎每一個倉庫都有 master 分支,是因為 git init 命令默認創建它,并且大多數人都懶得去改動它。

Git 怎么知道當前在哪一個分支上呢? 也很簡單,它有一個名為 HEAD 的特殊指針。?在 Git 中,HEAD 是一個指針,指向當前所在的本地分支(注:可以將 HEAD 想象為當前分支的別名)。

首次提交產生的提交對象沒有父對象,普通提交操作產生的提交對象有一個父對象,由多個分支合并產生的提交對象有多個父對象。

4.2 分支的查看、創建、切換、刪除

4.2.1 查看分支?git branch (選項 -v、-r、-a、--merged、--no-merged)

果不加任何參數運行 git branch,會得到當前所有分支的一個列表,* 字符代表當前所處的那一個分支(當前 HEAD 指針所指向的分支)。

If --list is given, or if there are no non-option arguments, existing branches are listed; the current branch will be highlighted in green and marked with an asterisk.?

使用 git branch -v?顯示本地分支列表,并顯示每個分支的最新提交的 SHA-1 值和提交信息。

git branch -r?顯示遠程跟蹤分支列表。

git branch -a?顯示所有分支列表,包括本地分支和遠程跟蹤分支。

使用 git branch --merged?查看哪些分支已經合并到當前分支。在這個列表中分支名字前沒有 * 號的分支通常可 以使用 git branch -d 刪除掉;你已經將它們的工作整合到了另一個分支,所以并不會失去任何東西。

使用 git branch --unmerged?查看所有包含未合并工作的分支。因為這個列表中的分支包含了還未合并的工作,嘗試使用 git branch -d 命令刪除這些分支時會失敗。

下面的例子中,沒有所有分支都已合入到 master 分支。

4.2.2 創建分支 git branch <branchname>?

Git 中,創建分支,即為創建一個可以移動的新的指針。比如,創建一個 testing 分支, 只需要使用 git branch 命令:git branch testing,這會在當前所在的提交對象上創建一個指針。git branch 命令僅僅創建一個新分支,并不會自動切換到新分支中去,因此當前你仍然在 master 分支上。

4.2.3 切換分支 git checkout 和 git switch

(1)git checkout

使用 git checkout 命令要切換到一個已存在的分支,比如,現在要切換到新創建的 testing 分支 去: git checkout testing,這樣 HEAD 就指向 testing 分支了

如果現在對項目中某文件做些修改,然后再提交一次,testing 分支將會向前移動,但 master 分支不動,仍然指向運行 git checkout 時所指的對象。

使用命令 git checkout master,切換回 master 分支。這條命令做了兩件事:(1)使 HEAD 指回 master 分支;(2)是將工作目錄恢復成 master 分支所指向的快照內容。也就是說,如果現在做修改,是始于一個較舊的版本,本質上來講,這就是忽略 testing 分支所做的修改,便于向另一個方向進行開發。

分支切換會改變你工作目錄中的文件。在切換分支時,一定要注意你工作目錄里的文件會被改變。 如果是切換到一個較舊的分支,工作目錄會恢復到該分支最后一次提交時的樣子。 如果 Git 不能干凈利落地完成這個任務, 它將禁止切換分支。

你可以簡單地使用 git log 命令查看分叉歷史。 運行 git log --oneline --decorate --graph --all,它會輸出你的提交歷史、各個分支的指向以及項目的分支分叉情況。

(2)git switch

The command "git branch <branchname>" will create the new branch, but it will not switch the working tree to it;?use "git switch <newbranch>" to switch to the new branch.

在 Git 2.23 版本之前,git checkout?用于切換分支、恢復文件、創建新分支等多種操作的命令。但是,從 Git 2.23 版本開始,它被拆分成了多個命令,以避免使用時的混淆。現在,git checkout?命令主要用于切換分支和恢復文件。例如,git checkout master?將當前分支切換到 master 分支,git checkout -- file.txt?將 file.txt 文件恢復到最近一次提交的狀態。

從 Git 2.23 版本開始,git switch?命令被引入用于切換分支。它的使用方式與 git checkout?類似,但是更加直觀和簡潔。例如,git switch master?將當前分支切換到 master 分支。

如果你使用的是 Git 2.23 及以上版本,建議使用 git switch?命令來切換分支,以避免混淆。如果你使用的是較老的 Git 版本,可以繼續使用 git checkout?命令,但需要注意其多種用法可能會導致一些意外情況。

4.2.4 創建并切換到此分支 git checkout -b <branchname>

git checkout -b?命令用于創建一個新的分支并切換到該分支(-b?參數表示創建一個新的分支)。比如,帶有 -b 參數的 git checkout 命令:git checkout -b iss53,實際上是下面兩條命令的簡寫:

$ git branch iss53?
$ git checkout iss53

執行該命令后,Git 會將當前分支的代碼復制到新的分支中,并將 HEAD 指向新的分支,你可以在新的分支上繼續開發代碼,而不影響當前分支的代碼。

4.2.5 刪除分支 git branch -d <branchname>

刪除未合并的分支需要使用 git branch -D刪除已合并的分支需要使用 git branch -d

4.3 分支的合并 git merge、git cherry-pick

使用 git merge 合并分支:先 check out 到想合并入的分支,然后執行 git merge。

Case 1:把 hotfix 分支合并入 master 分支

假設在當前項目中,先從?master 分支創建了一個?hotfix 分支,并在在 hotfix 分支提交了一些修改,現在想把 hotfix 分支修改的內容合并到 master。

提交歷史(checkout 到 master,然后執行 git merge):

你應該注意到了運行結果中的 "快進(fast-forward)"這個詞。 由于當前 master 分支所指向的提交是 hotfix 分支的提交的直接上游,所以 Git 只是簡單的將指針向前移動。 即:當你試圖合并兩個分支時,如果順著一個分支走下去能夠到達另一個分支,那么 Git 在合并兩者的時候,只會簡單的將指針向前推 進(指針右移),因為這種情況下的合并操作沒有需要解決的分歧——這就叫做 “快進(fast-forward)”。

Case 2:把 iss53 分支合并入 master 分支

hotfix 分支上所做的工作并沒有包含到 iss53 分支中,如果需要拉取 hotfix 所做的修改,可以使用 git merge master 命令將 master 分支合并入 iss53 分支;或者你也可以等到 iss53 分支完成其使命, 再將其合并回 master 分支。

在 Case 1 中,master 已經合入了 hotfix 分支的內容,快照流圖示如下:

如果在 iss53 分支上的工作完成了,可以考慮將其合并入 master 分支?。合并 iss53 分支到 master 分支與之前合并 hotfix 分支所做的工作差不多,只需要 checkout 到你想合并入的分支,然后運行 git merge 命令。

可以注意到,返回結果與之前合并 hotfix 分支的時候看起來有一點不一樣,這是因為,iss53 分支是從更早的地方分叉開的(diverged),master 分支已經前進,master 所在提交已經不是 iss53 分支所在提交的直接祖先。 出現這種情況的時候,Git 會使用兩個分支的末端所指的快照(C4 和 C5 )以及這兩個分支的工作祖先(C2),做一個簡單的三方合并。

Case 3:存在沖突

如果在兩個不同的分支中,對同一個文件的同一個部分進行了不同的修改,Git 就沒法干凈的合并它們。 比如,在上述例子中,如果 iss53?和 hotfix 兩個分支對同一個文件的同一處做了修改,合并它們的時候就會產生合并沖突。

看一個簡單的例子,項目的提交歷史如下:

# 在 master 分支新建一個 file1.txt 文件
$ git add file1.txt
$ git commit -m "master create file1.txt"# 新建 file2 分支,在這個分支上新建了 file2.txt 文件,同時對 file1.txt 追加了一行內容
$ git checkout -b file2
$ git add file2.txt
$ git commit -a -m "create file2 and file1 add a line"# 回到 master分支,對 file1.txt 文件追加一行內容
$ git checkout master
$ git commit -a -m "file1 add a line"# 把 file2 分支的修改內容并入到 master 分支
$ git branch -v
$ git merge file2

在當前的項目中,有 master 和 file2 兩個分支,都在 file2.txt 的末尾追加了一段文字,現在想合并這兩個分支:先 checkout 到 master,然后運行?git merge poem-1 命令。 由于兩個分支在相同的位置做了修改,存在沖突,合并時不知道采用哪一個,合并失敗:

任何因存在合并沖突而有待解決的文件,都會以未合并狀態標識出來,你可以在合并沖突后的任意時刻使用 git status 命令,查看那些因存在合并沖突而處于未合并 (unmerged)狀態的文件。Git 會在有沖突的文件中加入標準的沖突解決標記,這樣你可以打開這些包含沖突的文件,然后手動解決沖突。?

當前的例子中,兩個分支都對 file2.txt 文件做了修改,打開這個文件,顯示內容如下:

Git 用<<<<<<<,=======,>>>>>>> 標記出不同分支的內容,上述信息表示:HEAD 指示的版本,在 ======= 的上半部分,而 poem-1 指示的版本在 ======= 的下半部分。

為了解決沖突,你可以選擇使用由 ======= 分割的兩部分中的一個,或者自行合并這些內容。根據實際需要確定沖突解決方案,完成修改后把 >>>>>>,======= 和 >>>>>>> 這些行完全刪除。

在解決了所有文件里的沖突之后,對每個文件使用 git add 命令來將其標記為沖突已解決。 一旦暫存這些原本有沖突的文件,Git 就會將它們標記為沖突已解決,然后再執行 commit 提交即可。 ?

Case 4:儲藏現場 git stash

git stash?命令可以將當前工作目錄中未提交的修改 “儲藏” 起來,具體使用方法如下:

  1. 在工作目錄中進行一些修改;
  2. 運行 git stash?命令,將修改儲藏起來;
  3. 在進行其他操作之前,可以運行 git stash list?命令查看所有儲藏;
  4. 使用 git stash apply?命令恢復儲藏內容;
  5. 使用 git stash drop?命令刪除儲藏。

假設你當前有 master 和 dev 兩個分支,你臨時接到緊急任務,準備新建一個 issue-101 分支修復一個 bug,但是你在 dev 上進行的工作還沒有做完,還不能提交,這時,你可以用 git stash,把當前的工作現場儲藏起來,等以后恢復現場繼續工作。

運行過程:

# 保存現場
$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge
# 現在,用 git status查看工作區,是干凈的(除非有沒有被Git管理的文件)# 接下來創建分支修復 bug
$ git checkout master
$ git checkout -b issue-101
$ git commit -m "fix bug 101"
$ git switch master
$ git merge --no-ff -m "merged bug fix 101" issue-101# 恢復現場
$ git switch dev
$ git stash list
stash@{0}: WIP on dev: f52c633 add merge
# 工作現場還在,Git 把 stash 內容存在某個地方了,需要恢復:
# 方法1:用 git stash apply 恢復,恢復后 stash 內容并不刪除,需要用 git stash drop 刪除;
# 方法2:用 git stash pop,恢復的同時把 stash 內容刪除。$ git stash pop
$ git stash list
# 此時將看不到任何 stash 內容

Case 5:挑選提交合并 git cherry-pick <commitHash>

git merge?可以將兩個或多個分支合并成一個新的分支,它會將兩個分支的修改內容合并到一起,并生成一個新的提交記錄。git merge?會自動解決沖突,但有時會出現無法自動解決的沖突,需要手動解決。

如果你想將一個分支上的某個或某幾個提交記錄,復制到當前分支上,比如,要解決某個 bug 或者應用某個特定的功能,可以使用 git cherry-pick。

git cherry-pick?可以選擇性地將某個提交記錄合并到當前分支,而不會像 git merge 一樣將整個分支合并。git cherry-pick 將一個或多個提交應用到當前分支。它的作用是將指定的提交復制一份到當前分支上,相當于手動合并某個提交。

更多細節參考鏈接:Git 操作補充:cherry-pick、變基-CSDN博客

Case 6:變基 git rebase

在 Git 中,整合來自不同分支的修改,除了 merge,還有一種方法,變基 rebase。它可以將一個分支上的修改合并到另一個分支上。具體來說,Git 變基的操作是將當前分支的提交 “復制” 到目標分支上,然后將當前分支的指針指向目標分支的最新提交。這個過程中,Git 會嘗試將當前分支上的提交應用到目標分支上,如果發現沖突,需要手動解決沖突。

與 Git 合并 merge 不同,Git 變基可以重新定義提交歷史,使得提交歷史更加整潔和易于理解。Git 變基的優點是可以保持提交歷史的清晰,減少不必要的合并提交,從而更好地追蹤代碼的變化。不過,由于 Git 變基會修改提交歷史,因此需要謹慎使用,避免對已經共享的分支造成影響。

更多細節參考鏈接:Git 操作補充:cherry-pick、變基-CSDN博客

4.5?分支開發工作流

* 長期分支

Git 使用簡單的三方合并,所以就算在一段較長的時間內,反復把一個分支合并入另一個分支,也不是什么難事。 也就是說,在項目開發周期內,你可以同時擁有多個開放的分支,定期地把某分支合并入其他分支中。

使用多個長期分支的方法并非必要,但是這么做通常很有幫助,尤其是當你在一 個非常龐大或者復雜的項目中工作時,這樣做可以使你的分支具有不同級別的穩定性,當其具有一定程度的穩定性后,再把它合并入具有更高級別穩定性的分支中。

例子:只在 master 分支上保留完全穩定的代碼——有可能僅僅是已經發布或即將發布的代碼。 他們還有一些名為 develop 或者 next 的平行分支,被用來做后續開發或者測試穩定性——這些分支不必保持絕對穩定,但是一旦達到穩定狀態,它們就可以被合并入 master 分支了。

* 特性分支(短期分支)

特性分支對任何規模的項目都適用。 特性分支是一種短期分支,它被用來實現單一特性或其相關工作。

例子:在 master 分支上工作到 C1,這時為了解決一個問題 A 而新建 iss91 分支,在 iss91 分 支上工作到 C4,然而對于問題 A 你又有了新的想法,于是你再新建一個 iss91v2 分支試圖用另一種方法解決它,接著你回到 master 分支工作了一會兒,你又冒出了一個不太確定的想法,想為項目增加了新功能,便在 C10 的時候新建一個 dumbidea 分支,并在上面做些實驗。你的提交歷史看起來像下面這個樣子:

你最終決定使用在 iss91v2 分支中方案解決問題 A,同時,你將 dumbidea 分支拿給你的同事看,大家都覺得這部分內容值得保留,這時你可以拋棄 iss91 分支(丟棄 C5 和 C6 提交),然后把另外兩個分支合并入主干分支。最終你的提交歷史看起來像下面這個樣子:

5. 遠程倉庫?remote repository

5.1 相關概念

5.1.1 遠程倉庫 remote repository

Git 的遠程倉庫是指位于網絡上的 Git 倉庫(托管在因特網或其他網絡中的項目版本庫)。

它可以是位于本地局域網內的另一臺計算機,也可以是位于云端的服務器。Git 的遠程倉庫可以讓多個開發者在不同的地方協同開發同一個項目,通過上傳和下載代碼來實現代碼的共享和同步。

你可以有好幾個遠程倉庫,通常有些倉庫對你只讀,有些則可以讀寫。 與他人協作涉及管理遠程倉庫以及根據需要推送(push)或拉取(fetch)數據。

5.1.2 遠程分支 remote branch 和遠程跟蹤分支 remote-tracking branch

* 遠程分支

遠程分支即遠程倉庫上的分支,要在 Git 中創建遠程分支,需要使用 git push 命令。以下是創建遠程分支的步驟如下:

  1. 在本地創建一個新的分支,可以使用 git checkout -b 命令創建并切換到新分支。
  2. 在本地分支上進行了所需的更改。
  3. 使用 git push 命令將本地分支推送到遠程倉庫。例如,遠程倉庫名為 origin,可以使用以下命令將本地分支 mybranch 推送到遠程分支:git push origin mybranch,如果遠程倉庫不存在此分支,Git 會自動創建它。
  4. 使用 git branch -r 命令查看遠程分支列表,新遠程分支應該出現在列表中。

注意: 在推送分支之前,需要確保你有足夠的權限在遠程倉庫中創建分支,如果沒有權限,需要聯系倉庫管理員以獲取幫助。

git push 的語法規則可概括為:git push <遠程倉庫名> <本地分支名>:<遠程分支名>

如果你的本地分支與遠程分支同名,則可以省略遠程分支名。可以使用帶冒號 “:” 的格式來推送本地分支到一個命名不相同的遠程分支,比如,不想讓遠程倉庫上的分支叫做 serverfix,可以運行 git push origin serverfix:awesomebranch,將本地的 serverfix 分支推送到遠程倉庫上的 awesomebranch分支。

可以運行帶有 --delete 選項的 git push 命令來刪除一個遠程分支,比如,想要從服務器上刪除 serverfix 分支,運行命令:git push origin --delete serverfix

* 遠程跟蹤分支

執行 clone 后,遠程倉庫的分支會被克隆到本地,但是本地倉庫中的分支與遠程倉庫中的分支的發展不是完全同步的。為了跟蹤遠程倉庫中的分支,Git 會在本地倉庫中創建一個名為 remotes/remote-name/branch-name?的分支,這個分支就是 remote-tracking branch。?

remote branch?是指遠程倉庫上的分支。

remote-tracking branch 遠程跟蹤分支是遠程分支狀態的引用。它們是你不能移動的本地引用,當你做任何網絡通信操作時,它們會自動移動。 遠程跟蹤分支像是你上次連接到遠程倉庫時,那些分支所處狀態的書簽。它們以 (remote)/(branch) 形式命名。 比如,如果你想要看你最后一次與遠程倉庫 origin 通信時 master 分支的狀態,你可以查看 origin/master 分支。

可以通過 git branch -r?命令來查看所有遠程倉庫的分支,通過 git branch -a?命令來查看所有本地分支和遠程分支。

clone 遠程倉庫:使用 clone 命令克隆了一個倉庫,命令會自動將其添加為遠程倉庫并默認以 origin?為簡寫。即 Git 的 clone 命令會自動將這個遠程倉庫命名為 origin,拉取它的所有數據,創建一個指向此遠程倉庫?master 分支的指針,并且在本地將其命名為 origin/master(遠程跟蹤分支),Git 也會給你一個與 origin 的 master 分支在指向同一個地方的本地 master 分支(跟蹤分支),這樣你就有工作的基礎。

遠程倉庫的名字 origin?與分支名字 master?一樣,在 Git 中并沒有任何特別的含義。 master?是運行 git init 時默認的起始分支名字, origin?是運行 git clone 時默認的遠程倉庫名字。 如果運行 git clone -o booyah,那么默認的遠程分支名字將會是 booyah/master。

如果你在本地的 master 分支做了一些工作,然而在同一時間,其他人推送提交到遠程倉庫,更新了它的 master 分支,那么你的提交歷史將向不同的方向前進,但只要你不與 origin 服務器連接,你的 origin/master 指針就不會移動。

5.1.3 跟蹤分支

從一個遠程跟蹤分支檢出一個本地分支會自動創建一個 “跟蹤分支”(有時候也叫做 “上游分支”)。 跟蹤分支是與遠程分支有直接關系的本地分支。 如果在一個跟蹤分支上輸入 git pull,Git 能自動地識別去哪個服務器上抓取、合并到哪個分支。 當克隆一個倉庫時,它通常會自動地創建一個跟蹤 origin/master 的 master 分支

如果需要的話,可以通過運行 git checkout -b [branch] [remotename]/[branch] 設置其他跟蹤分支、跟蹤此倉庫的其他分支或者為其他倉庫設置跟蹤分支,這是一個十分常用的操作所以 Git 提供了 --track 快捷方式。

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.

Switched to a new branch 'serverfix'

此命令將創建一個用于工作的本地分支 serverfix,并且起點位于 origin/serverfix。

??

$ git checkout --track origin/serverfix

Branch serverfix set up to track remote branch serverfix from origin.

Switched to a new branch 'serverfix'

本地分支與遠程分支設置為不同名字,本地分支 sf 會自動從 origin/serverfix 拉取

$ git checkout -b sf origin/serverfix

Branch sf set up to track remote branch serverfix from origin.

Switched to a new branch 'sf'

可以使用帶有 -u 或 --set-upstream-to 選項的 git branch 顯式地設置已有的本地分支跟蹤一個剛剛拉取下來的遠程分支,或者修改正在跟蹤的上游分支。

$ git branch -u origin/serverfix

Branch serverfix set up to track remote branch serverfix from origin.

總結:Git 跟蹤分支是指本地倉庫中的分支,是基于本地倉庫中的提交記錄創建的,可以在本地進行修改、合并等操作。遠程跟蹤分支是指遠程倉庫中的分支,它們是基于遠程倉庫中的提交記錄創建的,不能直接在本地進行修改、合并等操作,需要通過拉取或推送遠程分支來進行操作。

5.2?查看遠程倉庫 git remote -v

git remote 顯示當前倉庫所關聯的遠程倉庫。
git remote -v 顯示詳細的遠程倉庫信息,包括遠程倉庫的名稱、fetch 和 push 的URL地址。
git remote show <remote-name> 查看某一個遠程倉庫的更多信息。

5.3?添加新的遠程倉庫 git remote add <shortname> <url>?

可以使用?git remote add <shortname> <url> 命令添加一個新的遠程 Git 倉庫,并為其指定一個方便引用的簡稱。

可以使用 git remote rename 修改遠程倉庫的簡寫名,即遠程倉庫重命名,比如,想要將 pb 重命名為 paul,可以運行:git remote rename pb paul,值得注意的是,這同樣也會修改你的遠程分支名字,過去那些引用 pb/master 的現在會引用 paul/master。

可以使用 git remote rm 移除遠程倉庫,如:git remote rm paul

5.4?從遠程倉庫拉取 git fetch <remote-name> 和 git pull?<remote-name>

5.4.1 git fetch

如果要同步你的工作,運行 git fetch origin 命令。 這個命令查找 origin?這個名字對應哪一個服務器,從中抓取本地沒有的數據,并且更新本地數據庫,移動 origin/master 指針指向新的、更新后的位置。

$ git remote
origin$ git remote add pb https://github.com/paulboone/ticgit$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push)$ git fetch pb
remote: Counting objects: 43, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 43 (delta 10), reused 31 (delta 5)
Unpacking objects: 100% (43/43), done.
From https://github.com/paulboone/ticgit ?
* [new branch] master -> pb/master ?
* [new branch] ticgit -> pb/ticgit

5.4.2 git pull

當 git fetch 命令從服務器上抓取本地沒有的數據時,git fetch 會將遠程倉庫的最新代碼下載到本地,但它并不會修改工作目錄中的內容,它只會獲取數據然后讓你自己合并,想要更新本地分支,你需要手動執行 git merge 或者 git rebase 命令來合并最新代碼。

通常來講,git pull 的含義是一個 git fetch 緊接著一個 git merge 命令。 如果有一個設置好的跟蹤分支(不管它是顯式設置的還是通過 clone 或 checkout 命令創建的),git pull 會查找當前分支所跟蹤的服務器與分支,從服務器上抓取數據然后嘗試合并入那個遠程分支。

總的來說,git fetch 更加安全,因為它不會自動合并代碼,你可以在合適的時候手動合并;而 git pull 更加方便,因為它可以自動合并代碼,讓你更快地獲取最新的代碼。

5.5?本地分支推送到遠程倉庫 git push

推送分支,就是把該分支上的所有本地提交推送到遠程庫。建議在 git push 之前先執行 git pull 命令,以確保本地代碼庫與遠程代碼庫同步。

如果遠程代碼庫中已經存在一些新的提交,而你本地的代碼庫沒有進行更新,那么你的 push 操作會被拒絕,因為你的本地代碼庫與遠程代碼庫不一致。

推送時,要指定本地分支,比如:運行 git push origin master,Git 會把 master 分支推送到遠程庫對應的遠程分支上。如果要推送其他分支,比如 dev,就用:git push origin dev。

多人協作小結:

  1. 首先,可以試圖用 git push origin <branch-name> 推送自己的修改;
  2. 如果推送失敗,則因為遠程分支比你的本地更新,需要先用 git pull 試圖合并;
  3. 如果合并有沖突,則解決沖突,并在本地提交;
  4. 沒有沖突或者解決掉沖突后,再用 git push origin <branch-name> 推送。

如果 git pull 提示 no tracking information,則說明本地分支和遠程分支的鏈接關系沒有創建,用命令 git branch --set-upstream-to <branch-name> origin/<branch-name>。

6. 問題記錄

6.1?添加 remote 信息時報錯:unable to get local isser certificate(服務器上SSL證書未經過第三方機構認證)

git config --global http.sslverify false

6.2?git pull fatal: refusing to merge unrelaterd histories

git pull origin master --allow-unrelated-histories

6.3 Pycharm 側邊欄沒有 Commit

Settings -> Version Control -> Commit -> 勾選 use non-modal commit interface -> Apply

7. 參考鏈接

Git安裝-Git入門-CSDNGit技能樹

Pro Git:Git - Book

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/40360.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/40360.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/40360.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

koa導出數據為csv文件給前端下載

后端代碼 async userActivityExport(ctx) {const limit ctx.query.limit || 2const offset ctx.query.offset || 0const UserActivity ctx.module.db().entity(userActivity)const findOption {}const ret await UserActivity.findMany_(findOption)const firtCol Objec…

QT5.12環境搭建與源碼編譯

一、概述 QT版本&#xff1a;QT5.12.10 Qt網址&#xff1a;http://download.qt.io/archive/qt/ 編譯平臺 ubuntu18.04 二、安裝交叉編譯工具鏈 1、獲取交叉編譯工具鏈 一般如果是編譯系統如果有對應的gcc 就是用這個就可以了 比如rk3128 lin…

【Qt】QTableWidget設置可以選擇多行多列,并能復制選擇的內容到剪貼板

比如有一個 QTableWidget*m_tbwQuery m_tbwQuery->installEventFilter(this); //進行事件過濾處理//設置可以選擇多行多列 m_tbwQuery->setSelectionMode(QAbstractItemView::MultiSelection); m_tbwQuery->setSelectionBehavior(QAbstractItemView::SelectItems); …

字符串相似度算法完全指南:編輯、令牌與序列三類算法的全面解析與深入分析

在自然語言處理領域&#xff0c;人們經常需要比較字符串&#xff0c;這些字符串可能是單詞、句子、段落甚至是整個文檔。如何快速判斷兩個單詞或句子是否相似&#xff0c;或者相似度是好還是差。這類似于我們使用手機打錯一個詞&#xff0c;但手機會建議正確的詞來修正它&#…

如何為老化的汽車鉛酸電池充電

一項小研究表明&#xff0c;汽車鉛酸電池不同于深循環或固定電池。汽車電池旨在限度地提高啟動電流容量&#xff0c;并且對深度放電或浮充(也稱為第 3 階段充電循環)反應不佳。起動電池的極板結構使表面積化&#xff0c;并且電解液比重 (SG) 高于其他電池&#xff0c;以提供高啟…

C# 實現位比較操作

1、目標 對兩個字節進行比較&#xff0c;統計變化位數、一位發生變化的位數、二位發生變化的位數、多位發生變化的位數。 2、代碼 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Lin…

php 跨域問題

設置header <?php $origin isset($_SERVER[HTTP_ORIGIN])? $_SERVER[HTTP_ORIGIN]:;$allow_originarray(http://www.aaa.com,http://www.bbb.com, ); if( $origin in $allow_origin ){header("Access-Control-Allow-Origin:".$origin);header("Access-Co…

Electron Forge 打包更改打包后圖片

確認 ICO 文件有效 確保 icon.ico 文件是有效的并且包含多種分辨率的圖標&#xff08;如 16x16, 32x32, 48x48, 256x256&#xff09;。可以使用工具如 icoconverter 來生成有效的 ICO 文件。 https://icoconvert.com/確認圖標文件路徑 確保圖標文件路徑正確并且文件存在。 確…

O2OA(翱途) 開發平臺之HTTP端口規劃

O2OA(翱途) 開發平臺[下稱O2OA開發平臺或者O2OA]采用相對靈活的系統架構&#xff0c;支持三種服務器運行的方式。本篇主要闡述合并服務運行獨立服務運行代理端口運行三種服務器運行方式。 一、先決條件&#xff1a; 1、O2Server服務器正常運行&#xff0c;系統安裝部署請參考文…

Vue84-Vuex的工作原理與搭建開發環境

一、vuex工作原理 stats&#xff1a;是一個object對象&#xff0c;里面有很多key-value&#xff0c;存放的就是要操作的數據。mutations&#xff1a;是一個object對象&#xff0c;真正去操作stats的人。actions的作用&#xff1a;是一個object對象&#xff0c;當一個動作對應的…

【Spring Boot】關系映射開發(一):一對一映射

關系映射開發&#xff08;一&#xff09;&#xff1a;一對一映射 1.認識實體間關系映射1.1 映射方向1.2 ORM 映射類型 2.實現 “一對一” 映射2.1 編寫實體2.1.1 新建 Student 實體2.1.2 新建 Card 實體 2.2 編寫 Repository 層2.2.1 編寫 Student 實體的 Repository2.2.2 編寫…

DFS,BFS最短路,樹與圖的深度/廣度優先遍歷,拓撲排序

DFS 例題&#xff1a;排列數字 在排列組合問題中&#xff0c;每個位置需要嘗試多個不同的數字組合&#xff0c;需要回溯以嘗試不同的可能性。因此&#xff0c;需要顯式地恢復現場&#xff08;撤銷標記&#xff09;&#xff0c;以確保每個可能的路徑都被探索。 #include <b…

從漣漪到波浪:資產代幣化的變革力量

原文標題&#xff1a;《From ripples to waves: The transformational power of tokenizing assets》撰文&#xff1a;Anutosh Banerjee&#xff0c;Matt Higginson&#xff0c;Julian Sevillano&#xff0c;Matt Higginson編譯&#xff1a;Chris&#xff0c;Techub News本文來…

還是NC,項目代碼開源|scRNA+bulkRNA+因子分析驗證地塞米松治療Covid19

說在前面 平時發文章的話&#xff0c;做藥物用的大多都是僅僅是GEO的bulkRNA&#xff0c;有人的有鼠的&#xff0c;然后做做流水線分析&#xff0c;最后面PCR。今天看一篇發NC的工作量&#xff0c;怎么用轉錄組分析做藥物的轉化免疫學 這篇文章作者已經上傳Github了&#xff…

LabVIEW自動探頭外觀檢測

開發了一套基于LabVIEW的軟件系統&#xff0c;結合視覺檢測技術&#xff0c;實現探頭及連接器外觀的自動檢測。通過使用高分辨率工業相機、光源和機械手臂&#xff0c;系統能夠自動定位并檢測探頭表面的細微缺陷&#xff0c;如劃痕、殘膠、異色、雜物等。系統支持多種探頭形態&…

Spark SQL----數據類型

Spark SQL----數據類型 一、支持的數據類型二、浮點特殊值三、正負無窮語義四、NaN語義五、例子 一、支持的數據類型 Spark SQL和DataFrames支持以下數據類型&#xff1a; Numeric類型 ByteType&#xff1a;表示1字節的帶符號整數。數字的范圍從-128到127。ShortType&#xf…

【C++ OpenCV】機器視覺-二值圖像和灰度圖像的膨脹、腐蝕、開運算、閉運算

原圖 結果圖 //包含頭文件 #include <opencv2/opencv.hpp>//命名空間 using namespace cv; using namespace std;//全局函數聲明部分//我的腐蝕運算 Mat Erode(Mat src, Mat Mask, uint32_t x0, uint32_t y0) {uint32_t x 0, y 0;Mat dst(src.rows, src.cols, CV_8U…

如何在忘記密碼的情況下重置Realme手機?

歡迎閱讀我們關于如何在有或沒有密碼的情況下重置Realme手機的綜合指南。無論您是忘記了密碼&#xff0c;還是只是需要將設備恢復到出廠設置&#xff0c;我們都會為您提供所需的專業提示和技術專長。 發現分步說明、專家提示和行之有效的方法&#xff0c;輕松重新控制您的 Rea…

Hadoop3:集群壓測-讀寫性能壓測

一、準備工作 首先&#xff0c;我們要知道&#xff0c;平常所說的網速和文件大小的MB是什么關系。 100Mbps單位是bit&#xff1b;10M/s單位是byte ; 1byte8bit&#xff0c;100Mbps/812.5M/s。 測試 配置102、103、104虛擬機網速 102上用Python開啟一個文件下載服務&#x…

Alpha2:使用深度強化學習挖掘公式化的超額收益因子(附論文及源代碼)

原創文章第577篇&#xff0c;專注“AI量化投資、世界運行的規律、個人成長與財富自由"。 今天說說因子挖掘&#xff0c;我們之前交付的Deap遺傳算法因子挖掘&#xff0c;大家可以前往溫習一下&#xff1a; 源碼發布Quantlab4.2&#xff0c;Deap因子挖掘|gplearn做不到的…