-
1. 起步
-
2. Git 基礎
-
3. Git 分支
-
4. 伺服器上的 Git
- 4.1 協議
- 4.2 在伺服器上部署 Git
- 4.3 生成 SSH 公鑰
- 4.4 架設伺服器
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方託管服務
- 4.10 小結
-
5. 分散式 Git
-
A1. 附錄 A: Git 在其他環境
- A1.1 圖形介面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 小結
-
A2. 附錄 B: 在應用程式中嵌入 Git
-
A3. 附錄 C: Git 命令
7.12 Git 工具 - 打包
打包
儘管我們已經介紹了透過網路傳輸 Git 資料的常用方法(HTTP、SSH 等),但實際上還有一種不常用但卻非常實用的方法。
Git 能夠將其資料“打包”成一個單一檔案。這在各種場景中都非常有用。例如,你的網路可能中斷了,但你想把更改傳送給同事。或者你正在異地工作,出於安全原因無法訪問本地網路。又或者你的無線/乙太網卡壞了。再或者你暫時無法訪問共享伺服器,想透過電子郵件傳送更新,但又不想透過 format-patch
傳輸 40 個提交。
這就是 git bundle
命令的用武之地。bundle
命令會將通常透過 git push
命令在網路上傳輸的所有內容打包成一個二進位制檔案,你可以將其透過電子郵件傳送給他人或放入快閃記憶體盤中,然後再解包到另一個倉庫中。
讓我們看一個簡單的例子。假設你有一個包含兩個提交的倉庫
$ git log
commit 9a466c572fe88b195efd356c3f2bbeccdb504102
Author: Scott Chacon <schacon@gmail.com>
Date: Wed Mar 10 07:34:10 2010 -0800
Second commit
commit b1ec3248f39900d2a406049d762aa68e9641be25
Author: Scott Chacon <schacon@gmail.com>
Date: Wed Mar 10 07:34:01 2010 -0800
First commit
如果你想把這個倉庫傳送給某人,而你又無法訪問可推送的倉庫,或者根本不想設定一個,你可以使用 git bundle create
命令將其打包。
$ git bundle create repo.bundle HEAD master
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 441 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
現在你有一個名為 repo.bundle
的檔案,其中包含了重新建立倉庫 master
分支所需的所有資料。使用 bundle
命令時,你需要列出所有要包含的引用或特定提交範圍。如果打算將其克隆到其他地方,你應該像我們在這裡做的那樣,將 HEAD 也新增為一個引用。
你可以將這個 repo.bundle
檔案透過電子郵件傳送給其他人,或者將其放入 U 盤中隨身攜帶。
另一方面,假設你收到了這個 repo.bundle
檔案,並想在這個專案上工作。你可以像從 URL 克隆一樣,從這個二進位制檔案克隆到一個目錄中。
$ git clone repo.bundle repo
Cloning into 'repo'...
...
$ cd repo
$ git log --oneline
9a466c5 Second commit
b1ec324 First commit
如果你沒有在引用中包含 HEAD,則還必須指定 -b master
或包含的任何分支,否則它將不知道要檢出哪個分支。
現在假設你對此進行了三次提交,並希望透過 U 盤或電子郵件將新的提交打包傳送回去。
$ git log --oneline
71b84da Last commit - second repo
c99cf5b Fourth commit - second repo
7011d3d Third commit - second repo
9a466c5 Second commit
b1ec324 First commit
首先,我們需要確定要包含在包中的提交範圍。與網路協議不同,網路協議會自動為我們計算出要在網路上傳輸的最小資料集,而我們需要手動計算。當然,你也可以像之前那樣打包整個倉庫,這也能行,但最好只打包差異——即我們剛剛在本地進行的三個提交。
為此,你需要計算差異。正如我們在提交範圍中所述,你可以透過多種方式指定提交範圍。要獲取我們 master
分支中但原始克隆分支中沒有的三個提交,我們可以使用 origin/master..master
或 master ^origin/master
。你可以使用 log
命令進行測試。
$ git log --oneline master ^origin/master
71b84da Last commit - second repo
c99cf5b Fourth commit - second repo
7011d3d Third commit - second repo
既然我們已經有了要包含在包中的提交列表,那麼就讓我們將它們打包吧。我們使用 git bundle create
命令來完成此操作,指定我們想要的包檔名以及要包含在其中的提交範圍。
$ git bundle create commits.bundle master ^9a466c5
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), 775 bytes, done.
Total 9 (delta 0), reused 0 (delta 0)
現在我們的目錄中有一個 commits.bundle
檔案。如果我們將其傳送給我們的夥伴,她就可以將其匯入到原始倉庫中,即使在此期間原始倉庫中又進行了更多工作。
當她收到包時,在將其匯入到她的倉庫之前,她可以檢查包以檢視其中包含什麼。第一個命令是 bundle verify
命令,它將確保檔案確實是一個有效的 Git 包,並且你擁有所有必要的祖先來正確地重構它。
$ git bundle verify ../commits.bundle
The bundle contains 1 ref
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
The bundle requires these 1 ref
9a466c572fe88b195efd356c3f2bbeccdb504102 second commit
../commits.bundle is okay
如果打包者只打包了他們最近的兩個提交,而不是全部三個,那麼原始倉庫將無法匯入它,因為它缺少所需的歷史記錄。verify
命令的結果會是這樣:
$ git bundle verify ../commits-bad.bundle
error: Repository lacks these prerequisite commits:
error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 Third commit - second repo
然而,我們的第一個包是有效的,所以我們可以從中抓取提交。如果你想檢視包中有哪些可以匯入的分支,還有一個命令可以列出所有頭:
$ git bundle list-heads ../commits.bundle
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
verify
子命令也會告訴你頭資訊。重點是檢視可以拉取哪些內容,因此你可以使用 fetch
或 pull
命令從這個包中匯入提交。在這裡,我們將包的 master
分支抓取到我們倉庫中名為 other-master
的分支:
$ git fetch ../commits.bundle master:other-master
From ../commits.bundle
* [new branch] master -> other-master
現在我們可以看到,除了我們自己的 master
分支中同時進行的任何提交外,other-master
分支上也有匯入的提交。
$ git log --oneline --decorate --graph --all
* 8255d41 (HEAD, master) Third commit - first repo
| * 71b84da (other-master) Last commit - second repo
| * c99cf5b Fourth commit - second repo
| * 7011d3d Third commit - second repo
|/
* 9a466c5 Second commit
* b1ec324 First commit
因此,當你不具備合適的網路或共享倉庫來進行共享或網路型別操作時,git bundle
會非常有用。