Following system colour scheme - Python 增強提案 Selected dark colour scheme - Python 增強提案 Selected light colour scheme - Python 增強提案

Python 增強提案

PEP 103 – 收集有關 Git 的資訊

作者:
Oleg Broytman <phd at phdru.name>
狀態:
已撤回
型別:
資訊性
建立日期:
2015 年 6 月 1 日
釋出歷史:
2015 年 9 月 12 日

目錄

重要

本 PEP 已撤回。

×

它過於通用,並沒有真正涉及 Python 開發。它不再更新。

內容已移至 Python Wiki。請在 wiki 中進行後續更新。

摘要

本資訊性 PEP 收集有關 Git 的資訊。當然,Git 有很多文件,因此本 PEP 重點關注更復雜(且與 Python 開發更相關)的問題、場景和示例。

計劃未來擴充套件本 PEP,收集 Mercurial 和 Git 場景的等效資訊,以幫助將 Python 開發從 Mercurial 遷移到 Git。

PEP 作者目前不打算撰寫關於將 Python 開發從 Mercurial 遷移到 Git 的流程 PEP。

文件

Git 附帶了大量線上和離線文件。

新手文件

Git 教程:第 1 部分, 第 2 部分

Git 使用者手冊日常 Git 與 20 條命令左右Git 工作流

高階文件

Git Magic,有多種語言翻譯。

Pro Git。關於 Git 的書。在 Amazon 購買或下載 PDF、mobi 或 ePub 格式。它有許多不同語言的翻譯。從 GArik 下載俄語翻譯。

Git Wiki.

Git Buch(德語)。

離線文件

Git 內建幫助:執行 git help $TOPIC。例如,執行 git help gitgit help help

快速開始

下載和安裝

Unix 使用者:使用您的包管理器下載並安裝

Microsoft Windows:下載 git-for-windows

MacOS X:使用 XCode 安裝的 Git,或從 MacPortsgit-osx-installer 下載,或使用 Homebrew 安裝 Git:brew install git

git-cola倉庫)是一個用 Python 編寫並採用 GPL 許可的 Git GUI。支援 Linux、Windows、MacOS X。

TortoiseGit 是一個基於 TortoiseSVN 的 Windows Shell Git 介面;開源。

初始配置

這段簡單的程式碼經常出現在文件中,但它很重要,所以在這裡重複一下。Git 在每次提交中儲存作者和提交者的姓名/電子郵件,因此請配置您的真實姓名和首選電子郵件

$ git config --global user.name "User Name"
$ git config --global user.email user.name@example.org

本 PEP 中的示例

本 PEP 中的 Git 命令示例採用以下方法。假設您(使用者)正在使用名為 python 的本地倉庫,該倉庫有一個名為 origin 的上游遠端倉庫。您的本地倉庫有兩個分支 v1master。對於大多數示例,當前檢出的分支是 master。也就是說,假設您已經做了類似的操作

$ git clone https://git.python.org/python.git
$ cd python
$ git branch v1 origin/v1

第一個命令將遠端倉庫克隆到本地目錄 python 中,建立一個新的本地分支 master,將其上游遠端跟蹤分支設定為 remotes/origin/master,並將其檢出到工作目錄中。

最後一個命令建立一個新的本地分支 v1 並將其上游遠端跟蹤分支設定為 remotes/origin/v1。

可以使用以下命令達到相同的結果

$ git clone -b v1 https://git.python.org/python.git
$ cd python
$ git checkout --track origin/master

最後一個命令建立一個新的本地分支 master,將其上游遠端跟蹤分支設定為 remotes/origin/master,並將其檢出到工作目錄中。

分支

Git 術語可能有點誤導。例如,“分支”這個術語。在 Git 中它有兩個含義。分支是提交的定向行(可能包含合併)。分支是分配給提交行的標籤或指標。區分何時談論提交以及何時談論它們的標籤很重要。提交行本身是未命名的,通常只會延長和合並。另一方面,標籤可以自由建立、移動、重新命名和刪除。

遠端倉庫和遠端分支

遠端跟蹤分支是您本地倉庫中的分支(指向提交的指標)。它們存在是為了讓 Git(和您)記住從哪個遠端倉庫拉取了哪些分支和提交,以及推送到哪個遠端倉庫(您可以從許多遠端倉庫拉取和推送到許多遠端倉庫)。遠端跟蹤分支位於 remotes/$REMOTE 名稱空間下,例如 remotes/origin/master

要檢視遠端跟蹤分支的狀態,請執行

$ git branch -rv

要檢視指向提交的本地和遠端跟蹤分支(和標籤)

$ git log --decorate

您永遠不會在遠端跟蹤分支上進行自己的開發。您建立一個具有遠端分支作為上游的本地分支,並在該本地分支上進行開發。在推送時,Git 將提交推送到遠端倉庫並更新遠端跟蹤分支;在拉取時,Git 從遠端倉庫獲取提交,更新遠端跟蹤分支並快進、合併或變基本地分支。

當你進行第一次克隆時,像這樣

$ git clone -b v1 https://git.python.org/python.git

git 將遠端倉庫 https://git.python.org/python.git 克隆到目錄 python,建立一個名為 origin 的遠端,建立遠端跟蹤分支,建立一個本地分支 v1,將其配置為跟蹤上游 remotes/origin/v1 分支,並將 v1 檢出到工作目錄中。

一些命令,例如 git status --branchgit branch --verbose,會報告本地分支和遠端分支之間的差異。請記住,它們只與您本地倉庫中的遠端跟蹤分支進行比較,並且這些遠端跟蹤分支的狀態可能已過時。要更新遠端跟蹤分支,您要麼從遠端倉庫 fetch 併合並(或 rebase)提交,要麼在不更新本地分支的情況下更新遠端跟蹤分支。

更新本地分支和遠端跟蹤分支

要在不更新本地分支的情況下更新遠端跟蹤分支,請執行 git remote update [$REMOTE...]。例如

$ git remote update
$ git remote update origin

Fetch 和 Pull

兩者之間存在重大差異

$ git fetch $REMOTE $BRANCH

$ git fetch $REMOTE $BRANCH:$BRANCH

第一個命令從 $REMOTE 倉庫中名為 $BRANCH 的分支獲取您倉庫中不存在的提交,更新遠端跟蹤分支,並將頭提交的 ID(雜湊值)留在檔案 .git/FETCH_HEAD 中。

第二個命令從 $REMOTE 倉庫中名為 $BRANCH 的分支獲取您倉庫中不存在的提交,並更新本地分支 $BRANCH 及其上游遠端跟蹤分支。但它在非快進的情況下拒絕更新分支。並且它拒絕更新當前分支(當前檢出的分支,即 HEAD 指向的分支)。

第一個命令由 git pull 在內部使用。

$ git pull $REMOTE $BRANCH

等價於

$ git fetch $REMOTE $BRANCH
$ git merge FETCH_HEAD

當然,在這種情況下,$BRANCH 應該是您的當前分支。如果您想將不同的分支合併到當前分支,請首先更新該非當前分支,然後合併

$ git fetch origin v1:v1  # Update v1
$ git pull --rebase origin master  # Update the current branch master
                                   # using rebase instead of merge
$ git merge v1

但是,如果您尚未推送 v1 上的提交,那麼場景會變得有點複雜。Git 拒絕更新不可快進的分支,並且您不想強制拉取,因為那會刪除您未推送的提交,您需要恢復。所以您想對 v1 進行變基,但您不能對非當前分支進行變基。因此,在合併之前檢出 v1 並對其進行變基

$ git checkout v1
$ git pull --rebase origin v1
$ git checkout master
$ git pull --rebase origin master
$ git merge v1

可以將 git 配置為一次性獲取/拉取幾個分支或所有分支,這樣您就可以簡單地執行

$ git pull origin

甚至

$ git pull

獲取/拉取的預設遠端倉庫是 origin。預設的引用集使用匹配演算法計算:git 獲取兩端具有相同名稱的所有分支。

Push

推送相對簡單。只有一個命令 push。當你執行

$ git push origin v1 master

git 將本地 v1 推送到遠端 v1,將本地 master 推送到遠端 master。與此相同

$ git push origin v1:v1 master:master

Git 將提交推送到遠端倉庫並更新遠端跟蹤分支。Git 拒絕推送非快進提交。無論如何,您可以強制推送,但請記住——您可以強制推送到您自己的倉庫,但不要強制推送到公共或共享倉庫。如果您發現 Git 拒絕推送非快進提交,最好從遠端倉庫 fetch 併合並提交(或在 fetch 的提交之上 rebase 您的提交),然後推送。只有當您知道自己在做什麼以及為什麼這樣做時才強制推送。請參閱下面的提交編輯和注意事項部分。

可以將 Git 配置為一次性推送幾個分支或所有分支,這樣您就可以簡單地執行

$ git push origin

甚至

$ git push

預設的推送遠端倉庫是 origin。Git 2.0 之前的預設推送引用集使用匹配演算法計算:Git 推送兩端具有相同名稱的所有分支。Git 2.0+ 中的預設推送引用集使用簡單演算法計算:Git 將當前分支推回其 @{upstream}。

要在 Git 2.0 之前配置為新行為,請執行

$ git config push.default simple

要在 Git 2.0+ 中配置為舊行為,請執行

$ git config push.default matching

如果分支是遠端非裸倉庫中的當前分支,Git 不允許推送該分支:Git 拒絕更新遠端工作目錄。您真的應該只推送到裸倉庫。對於非裸倉庫,Git 更喜歡基於拉取的工作流程。

當您想在遠端主機上部署程式碼並且只能使用推送(因為您的工作站位於防火牆後面,您無法從它拉取)時,您需要分兩步使用兩個倉庫來完成:您從工作站推送到遠端主機上的裸倉庫,透過 ssh 連線到遠端主機,然後從裸倉庫拉取到非裸部署倉庫。

這在 Git 2.3 中有所改變,但請參閱 這篇部落格文章 瞭解注意事項;在 2.4 中,push-to-deploy 功能 進一步改進

標籤

Git 在 fetch/pull 期間會自動獲取指向正在獲取的提交的標籤。要獲取所有標籤(及其指向的提交),請執行 git fetch --tags origin。要獲取某些特定標籤,請顯式獲取它們

$ git fetch origin tag $TAG1 tag $TAG2...

例如

$ git fetch origin tag 1.4.2
$ git fetch origin v1:v1 tag 2.1.7

Git 不會自動推送標籤。這允許您擁有私有標籤。要推送標籤,請明確列出它們

$ git push origin tag 1.4.2
$ git push origin v1 master tag 2.1.7

或者一次性推送所有標籤

$ git push --tags origin

標籤釋出後,請勿使用 git tag -f 移動標籤,或使用 git tag -d 刪除標籤。

私人資訊

當克隆/獲取/拉取/推送時,git 只複製資料庫物件(提交、樹、檔案和標籤)和符號引用(分支和輕量級標籤)。其他一切都對倉庫是私有的,從不克隆、更新或推送。這是您的配置、您的鉤子、您的私有排除檔案。

如果您想分發鉤子,請將它們複製到工作樹,新增、提交、推送,並指示團隊手動更新和安裝鉤子。

提交編輯和注意事項

文件中也出現了關於不要編輯已釋出(已推送)提交的警告,但鑑於其重要性,這裡仍然重複一遍。

從強制推送中恢復是可能的,但這對於整個團隊來說都是一個麻煩。請避免這樣做。

要檢視尚未釋出的提交,請將分支的頭部與其上游遠端跟蹤分支進行比較

$ git log origin/master..  # from origin/master to HEAD (of master)
$ git log origin/v1..v1  # from origin/v1 to the head of v1

對於每個具有上游遠端跟蹤分支的分支,Git 維護一個別名 @{upstream}(簡寫為 @{u}),因此上述命令可以表示為

$ git log @{u}..
$ git log v1@{u}..v1

檢視所有分支的狀態

$ git branch -avv

將本地分支狀態與遠端倉庫進行比較

$ git remote show origin

閱讀 如何從上游變基中恢復。它位於 git help rebase 中。

另一方面,不要太擔心提交編輯。您可以安全地編輯、重新排序、刪除、組合和拆分尚未推送的提交。您甚至可以將提交推送到您自己的(備份)倉庫,稍後編輯它們並強制推送編輯過的提交以替換已推送的內容。只要提交不在公共或共享倉庫中,就沒問題。

撤消

無論你做什麼,都不要驚慌。Git 中幾乎所有操作都可以撤消。

git checkout:恢復檔案內容

git checkout,例如,可以用來將檔案內容恢復到某個提交。像這樣

git checkout HEAD~ README

該命令將 README 檔案的內容恢復到當前分支倒數第二個提交。預設情況下,提交 ID 只是 HEAD;即 git checkout README 將 README 恢復到最新提交。

(不要使用 git checkout 來檢視提交中的檔案內容,請使用 git cat-file -p;例如 git cat-file -p HEAD~:path/to/README)。

git reset:移除(未推送的)提交

git reset 移動當前分支的頭部。頭部可以移動到指向任何提交,但它通常用於從分支頂部刪除一個或幾個提交(最好是未推送的),即向後移動分支以撤消幾個(未推送的)提交。

git reset 有三種操作模式——軟、硬和混合。預設是混合模式。ProGit 解釋了 它們之間的區別非常清楚。裸倉庫沒有索引或工作樹,因此在裸倉庫中只可能進行軟重置。

取消暫存

帶有路徑的混合模式重置可用於取消暫存更改——即,從索引中移除使用 git add 新增的更改以進行提交。有關取消暫存和其他撤消技巧的詳細資訊,請參閱 《Pro Git》

git reflog:引用日誌

使用 git reset 刪除提交或移動分支的頭部聽起來很危險,確實如此。但有一種方法可以撤銷:再次重置回原始提交。Git 不會立即刪除提交;未引用的提交(在 Git 術語中稱為“懸空提交”)會在資料庫中停留一段時間(預設為兩週),因此您可以重置回它或建立一個指向原始提交的新分支。

對於每次分支頭部的移動——無論是透過 git commitgit checkoutgit fetchgit pullgit rebasegit reset 等等——Git 都會儲存一個引用日誌(簡稱 reflog)。對於每次移動,Git 都會儲存頭部所在的位置。git reflog 命令可用於檢視(和操作)日誌。

除了每個分支頭部的移動之外,git 還儲存 HEAD 的移動——這是一個符號引用,(通常)它表示當前分支。HEAD 透過 git checkout $BRANCH 進行更改。

預設情況下,git reflog 顯示 HEAD 的移動,即該命令等效於 git reflog HEAD。要顯示分支頭部的移動,請使用命令 git reflog $BRANCH

因此,要撤消 git reset,請在 git reflog 中查詢原始提交,使用 git showgit log 進行驗證,然後執行 git reset $COMMIT_ID。Git 將分支頭部的移動儲存在 reflog 中,因此您以後可以再次撤消該撤消。

在更復雜的情況下,您可能希望在重置分支頭部的同時移動一些提交。將它們櫻桃挑選到新分支。例如,如果您想將 master 分支重置回原始提交,但保留當前分支中建立的兩個提交,請執行類似操作

$ git branch save-master  # create a new branch saving master
$ git reflog  # find the original place of master
$ git reset $COMMIT_ID
$ git cherry-pick save-master~ save-master
$ git branch -D save-master  # remove temporary branch

git revert:回滾提交

git revert 會回滾一個或多個提交,也就是說,它會建立一個或多個新的提交來回滾給定提交的效果。這是撤消已釋出提交的唯一方法(git commit --amendgit rebasegit reset 以非快進的方式更改分支,因此它們只應用於未推送的提交。)

回滾合併提交存在問題。git revert 可以撤消合併提交建立的程式碼,但它無法撤消合併的事實。請參閱討論 如何回滾錯誤的合併

無法撤消的事情

無論您撤銷什麼,有一件事是無法撤銷的——被覆蓋的未提交更改。未提交的更改不屬於 Git,因此 Git 無法幫助保留它們。

大多數情況下,當您要執行覆蓋未提交更改的命令時,Git 會警告您。Git 不允許您使用 git checkout 切換分支。當您在工作區不乾淨的情況下要進行變基時,它會阻止您。它拒絕在未提交的檔案上拉取新提交。

但是有些命令確實會這樣做——覆蓋工作樹中的檔案。像 git checkout $PATHsgit reset --hard 這樣的命令會默默地覆蓋檔案,包括您的未提交更改。

考慮到這一點,您就可以理解“儘早提交,經常提交”的立場了。儘可能經常提交。在編輯器或 IDE 中每次儲存時都提交。您可以在推送之前編輯您的提交——編輯提交訊息,更改提交,重新排序,組合,拆分,刪除。但請將您的更改儲存在 Git 資料庫中,要麼提交更改,要麼至少使用 git stash 將它們暫存起來。

合併還是變基?

網際網路上充斥著關於“合併還是變基?”的激烈討論。其中大多數毫無意義。當 DVCS 被用於一個龐大且複雜的專案、有許多分支的大型團隊時,根本無法避免合併。因此問題縮小為“是否使用變基,如果使用,何時使用變基?”考慮到強烈建議不要對已釋出的提交進行變基,問題進一步縮小為:“是否對未推送的提交使用變基?”

這個小問題由團隊決定。為了保持線性歷史的優美,建議在拉取時使用變基,即執行 git pull --rebase,甚至為每個新分支配置自動變基設定

$ git config branch.autosetuprebase always

併為現有分支配置變基

$ git config branch.$NAME.rebase true

例如

$ git config branch.v1.rebase true
$ git config branch.master.rebase true

此後,git pull origin master 等同於 git pull --rebase origin master

建議在單獨的功能分支或主題分支中建立新提交,同時使用變基來更新主線分支。當主題分支準備好後,將其合併到主線。為了避免一次性解決大量衝突的繁瑣任務,您可以不時將主題分支合併到主線,然後切換回主題分支繼續在其上工作。整個工作流程將是這樣的

$ git checkout -b issue-42  # create a new issue branch and switch to it
    ...edit/test/commit...
$ git checkout master
$ git pull --rebase origin master  # update master from the upstream
$ git merge issue-42
$ git branch -d issue-42  # delete the topic branch
$ git push origin master

當主題分支被刪除時,只移除了標籤,提交仍然保留在資料庫中,它們現在已合併到 master 中

o--o--o--o--o--M--< master - the mainline branch
    \         /
     --*--*--*             - the topic branch, now unnamed

刪除主題分支是為了避免用小主題分支弄亂分支名稱空間。關於修復了什麼問題或實現了什麼功能的資訊應該在提交訊息中。

但即使是少量變基,對於長期合併的分支來說也可能太多。想象一下,您正在 v1master 分支中工作,定期將 v1 合併到 master。一段時間後,您將在 master 中擁有大量合併和非合併提交。然後您想將完成的工作推送到共享倉庫,卻發現有人向 v1 推送了幾個提交。現在您有兩種同樣糟糕的選擇:要麼獲取並變基 v1,然後不得不重新建立 master 中的所有工作(將 master 重置到 origin,合併 v1 並從舊的 master 中櫻桃挑選所有非合併提交);要麼合併新的 v1 並失去線性歷史的優美。

空合併

Git 有一個內建的合併策略,用於 Python 核心開發者所稱的“空合併”

$ git merge -s ours v1  # null-merge v1 into master

分支模型

Git 不假定任何特定的分支和合並開發模型。有些專案傾向於將補丁從最舊的分支升級到最新,有些傾向於反向櫻桃選擇提交,有些使用 squashing(將多個提交合併為一個)。一切皆有可能。

有一些例子可以作為起點。git help workflows 描述了 Git 作者如何開發 Git。

ProGit 書中有幾章專門討論不同專案中的分支管理:Git 分支 - 分支工作流分散式 Git - 貢獻到專案

Vincent Driessen 還發表了一篇著名的文章 一個成功的 Git 分支模型。它推薦了一套非常詳細的規則,用於建立和管理主線、主題和錯誤修復分支。為了支援該模型,作者實現了 git flow 擴充套件。

高階配置

行尾符

Git 內建機制可處理不同行尾樣式平臺之間的行尾問題。要讓 Git 進行 CRLF 轉換,請使用 .gitattributes 為檔案分配 text 屬性。對於必須具有特定行尾的檔案,請分配 eol 屬性。對於二進位制檔案,屬性自然是 binary

例如

$ cat .gitattributes
*.py text
*.txt text
*.png binary
/readme.txt eol=CRLF

要檢查 Git 為檔案使用的屬性,請使用 git check-attr 命令。例如

$ git check-attr -a -- \*.py

有用的資源

GitAlias倉庫)是大量的別名集合。仔細選擇常用命令的別名可以節省您大量的擊鍵!

GitIgnorehttps://github.com/github/gitignore 是適用於各種 IDE 和程式語言的 .gitignore 檔案集合。包括 Python!

pre-commit倉庫)是一個用於管理和維護多語言 pre-commit 鉤子的框架。該框架用 Python 編寫,擁有許多用於多種程式語言的外掛。

高階主題

暫存區

暫存區,又稱索引或快取,是 Git 的一個顯著特性。暫存區是 Git 在提交補丁之前收集補丁的地方。收集補丁和提交階段的分離提供了 Git 一個非常有用的功能:您可以在提交之前檢視收集到的補丁,甚至可以編輯它們——刪除一些程式碼塊,新增新的程式碼塊,然後再次檢視。

要將檔案新增到索引,請使用 git add。在提交之前收集補丁意味著您需要對每次更改都這樣做,而不僅僅是新增新的(未跟蹤的)檔案。為了簡化提交,如果您只想在不審查的情況下提交所有內容,請執行 git commit --all(或簡寫 -a)——該命令會將每個更改的已跟蹤檔案新增到索引,然後提交。要提交一個或多個檔案,而不考慮索引中收集的補丁,請執行 git commit [--only|-o] -- $FILE...

要將補丁塊新增到索引,請使用 git add --patch(或簡寫 -p)。要從索引中刪除已收集的檔案,請使用 git reset HEAD -- $FILE...。要新增/檢查/刪除已收集的補丁塊,請使用 git add --interactive-i)。

要檢視索引和上次提交之間的差異(即收集到的補丁),請使用 git diff --cached。要檢視工作樹和索引之間的差異(即未收集的補丁),請只使用 git diff。要檢視工作樹和上次提交之間的差異(即收集和未收集的補丁),請執行 git diff HEAD

參見 Git Wiki 中的 WhatIsTheIndexIndexCommandQuickref

根目錄

Git 在執行任何命令之前會切換到根目錄(專案頂層目錄,其中包含 .git 子目錄)。但 Git 會記住切換前所在的當前目錄。有些程式會考慮當前目錄。例如,git status 顯示相對於當前目錄的更改和未知檔案的路徑;git grep 在當前目錄下方搜尋;git apply 只應用補丁中影響當前目錄下方檔案的 hunk。

但大多數命令都是從根目錄執行並忽略當前目錄的。例如,假設您有兩個工作樹,一個用於 v1 分支,另一個用於 master。如果您想在第二個工作樹內的子目錄中合併 v1,您必須像在頂層目錄中一樣編寫命令。例如,假設有兩個工作樹,project-v1project,例如

$ cd project/subdirectory
$ git fetch ../project-v1 v1:v1
$ git merge v1

請注意,在 git fetch ../project-v1 v1:v1 中,路徑是 ../project-v1,而不是 ../../project-v1,儘管我們是從子目錄而不是根目錄執行命令。

ReReRe

Rerere 是一種幫助解決重複合併衝突的機制。重複合併衝突最常見的來源是將主題分支合併到主線中然後刪除合併提交;這通常用於測試主題分支並訓練 rerere;刪除合併提交是為了擁有乾淨的線性歷史,並以僅一個最終合併提交結束主題分支。

Rerere 的工作原理是記住成功提交前後樹的狀態。這樣,如果衝突出現在相同的檔案中,rerere 就可以自動解決它們。

Rerere 可以使用 git rerere 命令手動使用,但最常自動使用。在工作樹中啟用 rerere,使用以下命令

$ git config rerere.enabled true
$ git config rerere.autoupdate true

您不需要全域性開啟 rerere——您不需要在裸倉庫或單分支倉庫中使用 rerere;您只需要在經常執行合併和解決合併衝突的倉庫中使用 rerere。

請參閱《Pro Git》中的 Rerere

資料庫維護

Git 物件資料庫和 .git 下的其他檔案/目錄需要定期維護和清理。例如,提交編輯會留下未引用的物件(在 Git 術語中稱為懸空物件),這些物件應該被修剪以避免在資料庫中堆積垃圾。命令 git gc 用於維護。Git 自動將 git gc --auto 作為某些命令的一部分執行,以進行快速維護。建議使用者不時執行 git gc --aggressivegit help gc 建議每隔幾百個變更集執行一次;對於更密集的專案,應該像每週一次,對於不那麼活躍的專案則不那麼頻繁(每兩週或每月一次)。

git gc --aggressive 不僅刪除懸空物件,它還將物件資料庫重新打包成索引和更最佳化的包;它還會打包符號引用(分支和標籤)。另一種方法是執行 git repack

Linus Torvalds 有一則著名的 訊息,關於 git gc --aggressive 的“愚蠢”。現在這條訊息可以安全地忽略了。它已經過時了,從那時起 git gc --aggressive 已經變得好很多了。

對於那些仍然喜歡 git repack 而不是 git gc --aggressive 的人,推薦的引數是 git repack -a -d -f --depth=20 --window=250。有關這些引數影響的解釋,請參閱 這個詳細實驗

不時執行 git fsck [--strict] 來驗證資料庫的完整性。git fsck 可能會生成一個懸空物件列表;這不是錯誤,只是提醒您進行定期維護。

技巧和竅門

命令列選項和引數

git help cli 建議不要組合短選項/標誌。大多數情況下組合是有效的:git commit -av 完美執行,但有時不起作用。例如,git log -p -5 不能組合成 git log -p5

有些選項帶有引數,有些甚至有預設引數。在這種情況下,此類選項的引數必須以粘連方式拼寫:-Oarg,切勿 -O arg,因為對於具有預設引數的選項,後者表示“使用選項 -O 的預設值並將 arg 進一步傳遞給選項解析器”。例如,git grep 有一個選項 -O,它將找到的檔名列表傳遞給一個程式;-O 的預設程式是分頁器(通常是 less),但您可以使用您的編輯器

$ git grep -Ovim  # but not -O vim

順便說一句,如果 Git 被指示使用 less 作為分頁器(即,如果 Git 中根本沒有配置分頁器,它預設使用 less,或者如果它從 GIT_PAGER 或 PAGER 環境變數中獲取 less,或者如果它配置了 git config [--global] core.pager less,或者 less 在命令 git grep -Oless 中使用),git grep 會將 +/$pattern 選項傳遞給 less,這非常方便。不幸的是,如果分頁器不是精確的 less,即使是帶有引數的 less(例如 git config [--global] core.pager less -FRSXgimq),git grep 也不會傳遞模式;幸運的是,git grep -Oless 總是傳遞模式。

bash/zsh 補全

即使對於那些樂於使用命令列的人來說,手動鍵入 git rebase --interactive --preserve-merges HEAD~5 也有點困難,而這就是 shell 補全大有幫助的地方。Bash/zsh 帶有可程式設計補全功能,通常會自動安裝和啟用,所以如果你安裝了 bash/zsh 和 git,很可能你已經完成了——只需在命令列中使用它即可。

如果您沒有安裝必要的元件,請安裝並啟用 bash_completion 包。如果您想將 Git 補全升級到最新版本,請從 git contrib 下載必要的檔案。

Git-for-windows 附帶 git-bash,其中已安裝並啟用了 bash 補全。

bash/zsh 提示符

對於命令列愛好者來說,shell 提示符可以攜帶大量有用的資訊。要將 Git 資訊包含在提示符中,請使用 git-prompt.sh。請閱讀檔案中的詳細說明。

在網上搜索“git prompt”以查詢其他提示符變體。

SSH 連線共享

SSH 連線共享是 OpenSSH 以及 PuTTY 等衍生產品的一項功能。SSH 連線共享是一種透過建立一個連線並將其重用於連線到同一伺服器的所有後續客戶端來減少 ssh 客戶端啟動時間的方法。SSH 連線共享可用於加速大量短 ssh 會話,例如 scp、sftp、rsync,當然還有透過 ssh 的 Git。如果您經常從/向可透過 ssh 訪問的遠端倉庫 fetch/pull/push,建議使用 ssh 連線共享。

要開啟 SSH 連線共享,請在您的 ~/.ssh/config 中新增類似以下內容

Host *
ControlMaster auto
ControlPath ~/.ssh/mux-%r@%h:%p
ControlPersist 600

請參閱 OpenSSH wikibook搜尋 瞭解更多資訊。

SSH 連線共享可以在 GitHub、GitLab 和 SourceForge 倉庫上使用,但請注意 BitBucket 不允許這樣做,並在短時間不活動後強制關閉主連線,因此您會看到來自 ssh 的類似錯誤:“與 bitbucket.org 的連線被遠端主機關閉。”

伺服器上的 Git

釋出倉庫或一組倉庫的最簡單方法是 git daemon。該守護程序提供匿名訪問,預設情況下是隻讀的。倉庫可以透過 git 協議(git:// URL)訪問。可以啟用寫入訪問,但該協議缺少任何身份驗證手段,因此只能在受信任的區域網內啟用。有關詳細資訊,請參閱 git help daemon

透過 ssh 提供的 Git 提供了身份驗證和倉庫級別的授權,因為倉庫可以設定為使用者或組可寫(參見 git help config 中的引數 core.sharedRepository)。如果這對於某些專案需求來說過於寬鬆或過於嚴格,可以使用封裝器 gitolite,它可以配置為提供精細的訪問控制;gitolite 用 Perl 編寫,擁有大量文件。

可以使用 gitwebcgit 建立用於瀏覽倉庫的 Web 介面。兩者都是 CGI 指令碼(分別用 Perl 和 C 編寫)。除了 Web 介面,兩者還為 Git 提供只讀的簡單 HTTP 訪問(http(s):// URL)。Klaus 是一個小型簡單的 WSGI Web 伺服器,它實現了 Web 介面和 Git 智慧 HTTP 傳輸;支援 Python 2 和 Python 3,並執行語法高亮。

還有更高階的基於網路的開發環境,包括管理使用者、組和專案的功能;私有、組可訪問和公共倉庫;它們通常包括問題跟蹤器、維基頁面、拉取請求以及其他用於開發和通訊的工具。這些環境包括 Kallitheapagure,兩者都用 Python 編寫;pagure 由 Fedora 開發者編寫,並被用於開發一些 Fedora 專案。GitPrep 是另一個 GitHub 克隆,用 Perl 編寫。Gogs 用 Go 編寫。GitBucket 用 Scala 編寫。

最後但同樣重要的是,GitLab。它可能是 Git 最先進的基於 Web 的開發環境。用 Ruby 編寫,社群版免費開源(MIT 許可證)。

從 Mercurial 到 Git

有許多工具可以將 Mercurial 倉庫轉換為 Git。最著名的可能就是 hg-gitfast-export(多年前它被稱為 hg2git)。

但一個更好的工具,也許是最好的,是 git-remote-hg。它提供了從 Git 透明地雙向(拉取和推送)訪問 Mercurial 倉庫。它的作者寫了一篇 替代品比較,這看起來大部分是客觀的。

要使用 git-remote-hg,請安裝或克隆它,新增到您的 PATH(或將指令碼 git-remote-hg 複製到已在 PATH 中的目錄),並在 Mercurial URL 前面加上 hg::。例如

$ git clone https://github.com/felipec/git-remote-hg.git
$ PATH=$PATH:"`pwd`"/git-remote-hg
$ git clone hg::https://hg.python.org/peps/ PEPs

要使用倉庫,只需使用常規的 Git 命令,包括 git fetch/pull/push

要開始將您的 Mercurial 習慣轉換為 Git,請參閱 Mercurial wiki 上的頁面 Mercurial for Git users。頁面後半部分有一個表格,列出了相應的 Mercurial 和 Git 命令。應該在兩個方向上都完美執行。

Python 開發者指南中也有一章 Mercurial for git developers,其中記錄了 Git 和 hg 之間的一些區別。

Git 和 GitHub

gitsome - Git/GitHub 命令列介面 (CLI)。用 Python 編寫,可在 MacOS、Unix、Windows 上執行。Git/GitHub CLI 具有自動補全功能,包括許多與所有 shell 配合使用的 GitHub 整合命令,內建帶有 Python REPL 的 xonsh,可同時執行 Python 命令和 shell 命令,命令歷史記錄,可自定義高亮顯示,文件詳盡。


來源: https://github.com/python/peps/blob/main/peps/pep-0103.rst

最後修改: 2024-04-14 20:08:31 GMT