-
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
文件通过电子邮件发送给其他人,或将其放在 USB 驱动器上并走过去。
另一方面,假设你收到了一个 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
或包含的任何分支,因为否则 Git 将不知道要检出哪个分支。
现在假设你在上面做了三个提交,并且想要通过 USB 存储器或电子邮件以 bundle 的形式将新的提交发回。
$ git log --oneline
71b84da Last commit - second repo
c99cf5b Fourth commit - second repo
7011d3d Third commit - second repo
9a466c5 Second commit
b1ec324 First commit
首先,我们需要确定想要包含在 bundle 中的提交范围。与网络协议会自动找出通过网络传输的最小数据集不同,我们需要手动计算。当然,你可以直接做同样的事情,打包整个存储库,这也能工作,但最好只打包差异部分,即我们刚刚在本地所做的三个提交。
为了做到这一点,你需要计算差异。正如我们在 提交范围 中描述的那样,你可以用多种方式指定提交范围。为了获取我们在 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
现在我们有了想要包含在 bundle 中的提交列表,让我们将它们打包起来。我们使用 git bundle create
命令来完成,为它提供我们想要的 bundle 文件名以及我们想要放入其中的提交范围。
$ 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 时,她可以检查它以查看其中包含的内容,然后再将其导入到她的存储库中。第一个命令是 bundle verify
命令,它将确保该文件实际上是一个有效的 Git bundle,并且你拥有所有必要的祖先来正确地重构它。
$ 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
如果打包者只创建了他们所做的最后两次提交的 bundle,而不是全部三次,那么原始存储库将无法导入它,因为它缺少必要的历史记录。 verify
命令会像这样显示错误:
$ git bundle verify ../commits-bad.bundle
error: Repository lacks these prerequisite commits:
error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 Third commit - second repo
但是,我们的第一个 bundle 是有效的,所以我们可以从中获取提交。如果你想查看 bundle 中可以导入的分支,还有一个命令可以只列出 heads。
$ git bundle list-heads ../commits.bundle
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
verify
子命令也会告诉你 heads。重点是查看可以拉入的内容,所以你可以使用 fetch
或 pull
命令从这个 bundle 中导入提交。在这里,我们将 bundle 的 master
分支 fetch 到我们存储库中名为 other-master
的分支中。
$ git fetch ../commits.bundle master:other-master
From ../commits.bundle
* [new branch] master -> other-master
现在我们可以看到,我们在 other-master
分支上拥有导入的提交,以及我们在此期间在我们自己的 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
可以非常有用,可以进行共享或执行网络类型的操作。