【Git 学习笔记_21】第十章 Git 补丁与离线共享(下)

第十章 Git 补丁与离线共享(下)

本章相关主题

  • 补丁的创建(见上篇)
  • 从分支创建补丁(见上篇)
  • 补丁的应用(见上篇)
  • 补丁的发送
  • 创建 Git 打包文件(bundles)
  • 使用 Git 打包文件(bundle)
  • 创建基于 tree 的存档文件

10.4 补丁的发送

Git 还可以通过命令 git send-email 直接已电子邮件的方式发送补丁。不过该命令需要手动配置,且相关配置严重依赖具体的邮箱和 SMTP 协议要求。相关配置信息参考:http://git-scm.com/docs/git-send-email。

这里仅供演示:

$ git clone https://github.com/PacktPublishing/Git-Version-Control-Cookbook-Second-Edition_offline-sharing.git
$ cd Git-Version-Control-Cookbook-Second-Edition_offline-sharing
$ git format-patch -1 -o latest-commit
latest-commit/0001-Calculate-pi-with-more-digits.patch
$ emailaddr=$(git config user.email)
$ git send-email --to $emailaddr --from $emailaddr latest-commit/0001-Calculate-pi-with-more-digits.patch
latest-commit/0001-Calculate-pi-with-more-digits.patch
(mbox) Adding cc: John Doe <john.doe@example.com> from line 'From: John Doe <john.doe@example.com>'
  OK. Log says:
  Server: smtp.gmail.com
  MAIL FROM:<john.doe@example.com>
  RCPT TO:<john.doe@example.com>
  From: john.doe@example.com
  To: john.doe.example.com
  Subject: [PATCH] Calculate pi with more digits
  Date: Mon, 14 Apr 2014 09:00:11 +0200
  Message-Id: <1397458811-13755-1-git-send-email-john.doe@example.com>
  X-Mailer: git-send-email 1.9.1 

# using --cover-letter:
$ git checkout develop
Switched to branch 'develop'
Your branch is up-to-date with 'origin/develop'.
$ git send-email --to john.doe@example.com --from john.doe@example.com --cover-letter --annotate origin/master

10.5 创建 Git 打包文件(bundles)

Git 还可以通过打包文件(bundles)共享提交历史。打包文件是可以用作远程仓库的一组 commit,可以不包含 git 库的所有提交记录。

$ git clone https://github.com/PacktPublishing/Git-Version-Control-Cookbook-Second-Edition_offline-sharing.git offline-sharing
$ cd offline-sharing
$ git checkout master; git checkout develop; git checkout master
# create root bundle
$ git bundle create myrepo.bundle master
create myrepo.bundle master
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Compressing objects: 100% (12/12), done.
Total 13 (delta 1), reused 9 (delta 0), pack-reused 0
# verify bundle
$ git bundle verify myrepo.bundle
myrepo.bundle is okay
The bundle contains this ref:
937f9602dcd2236397c916d1ac764efcfa5e97cd refs/heads/master
The bundle records a complete history.
# give it a tag
$ git tag bundleForOtherRepo master

在创建的根包的基础上,再次创建同名的第二个包,会覆盖掉之前的根包文件。新的包中包含了标识标签到 develop 分支的历史记录:

$ git bundle create .\myrepo.bundle bundleForOtherRepo..develop
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Compressing objects: 100% (7/7), done.
Total 9 (delta 2), reused 9 (delta 2), pack-reused 0
$ git bundle verify myrepo.bundle
myrepo.bundle is okay
The bundle contains this ref:
0276427284e6d86aca623ec68b974b860e9c3d1b refs/heads/develop
The bundle requires this ref:
2a6f0eb9e9a9bb339aa00daa3ecd05c9a730a28d

这时可以在 gitk 查看 masterdevelop 分支:gitk master develop

master vs develop

小贴士

第二个包和根包重名是有其合理性的。在下一节演示中您将看到,打包文件将作为远程库关联到当前库中,其 URL 是打包文件的 文件路径。如果后续的打包文件路径不变(覆盖原名),则之后同步远程库只需执行 fetch 就能轻松实现。

10.6 使用 Git 打包文件(bundle)

本节演示 git 打包文件的使用:

# Init repo
$ rm -rf offline-sharing
$ git clone https://github.com/PacktPublishing/Git-Version-Control-Cookbook-Second-Edition_offline-sharing.git
$ cd Git-Version-Control-Cookbook-Second-Edition_offline-sharing 
$ git checkout master 
$ git bundle create myrepo.bundle master
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Compressing objects: 100% (12/12), done.
Total 13 (delta 1), reused 9 (delta 0), pack-reused 0
$ git tag bundleForOtherRepo master
# Demo: create repo from bundle file
$ cd ..
$ git clone -b master Git-Version-Control-Cookbook-Second-Edition_offline-sharing/myrepo.bundle offline-other
Cloning into 'offline-other'...
Receiving objects: 100% (13/13), done.
Resolving deltas: 100% (1/1), done.
$ cd offline-other
$ git log --oneline --decorate --all

执行结果:

git log in offline-other

符合预期。接下来创建第二个打包文件,范围从标识标签到 develop 分支:

$ cd ..
$ cd Git-Version-Cookbook-Second-Edition_offline-sharing
$ git checkout develop
$ git checkout master
$ git bundle create myrepo.bundle bundleForOtherRepo..develop
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Compressing objects: 100% (7/7), done.
Total 9 (delta 2), reused 9 (delta 2), pack-reused 0
$ git bundle verify myrepo.bundle
myrepo.bundle is okay
The bundle contains this ref:
0276427284e6d86aca623ec68b974b860e9c3d1b refs/heads/develop
The bundle requires this ref:
2a6f0eb9e9a9bb339aa00daa3ecd05c9a730a28d

实测过程中发现,创建第二个打包文件需要先签出 develop 分支到本地,否则报错:

# if develop branch is not checkout locally
$ git bundle create .\myrepo.bundle  bundleForOtherRepo..develop
fatal: ambiguous argument 'bundleForOtherRepo..develop': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

根据提示,新的打包文件需要一个 commit2a6f0eb9e9a9bb339aa00daa3ecd05c9a730a28d。在 offline-other 文件夹中进行验证:

$ cd ..
$ cd offline-other
$ git show -s 2a6f0eb9e9a9bb339aa00daa3ecd05c9a730a28d
commit 2a6f0eb9e9a9bb339aa00daa3ecd05c9a730a28d
Author: John Doe <john.doe@example.com>
Date:   Wed Apr 9 21:28:51 2014 +0200

    Adds checker for prime number

验证通过,说明新打包文件可以直接应用到这个库,执行 git fetch 即可:

$ git fetch
Receiving objects: 100% (9/9), done.
Resolving deltas: 100% (2/2), done.
From C:/Users/z/Desktop/Git-Version-Control-Cookbook-Second-Edition_offline-sharing/myrepo.bundle
 * [new branch]      develop    -> origin/develop

接着签出 develop 分支,此时 master 与 develop 应该与原仓库一致:

$ git checkout develop
$ gitk --all

运行结果如下:(符合预期)

compare master develop

小贴士

git 打包文件适用于设备间没有网络连接、或因为防火墙受限而无法使用正常共享提交历史的情况。其主要优点是每次需要更新远程时,无需将整个历史记录写入 bare 库,而只需将需要同步的部分写入打包文件即可。

10.7 创建基于 tree 的存档文件

若是不考虑提交历史,怎样像 commit 提交那样,得到一个项目的目录结构快照呢?你可以忽略 .git 文件夹,从某个指定版本创建一个存档文件(archive)。Git 有专门的命令处理类似场景,可以基于特定的版本或引用来实现。但要注意,用 Git 创建的存档文件仅包含被 Git 纳入版本管理的内容,工作区中不参与版本控制的文件或文件夹是不在该存档范围内的。

本节仍以 offline-sharing 库为例进行演示,在 master 分支的最新版本上创建存档(原书中默认为 develop 分支的说法与实测并不相符):

# Init repo
$ git clone https://github.com/PacktPublishing/Git-Version-Control-Cookbook-Second-Edition_offline-sharing.git
$ cd Git-Version-Control-Cookbook-Second-Edition_offline-sharing
# Create archive
$ git archive --prefix=offline/ -o offline.zip master
$ unzip -l offline.zip
Archive:  offline.zip
937f9602dcd2236397c916d1ac764efcfa5e97cd
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2021-01-15 15:34   offline/
      162  2021-01-15 15:34   offline/README.md
      485  2021-01-15 15:34   offline/another_pi.c
      672  2021-01-15 15:34   offline/math.c
---------                     -------
     1319                     4 files
# Check with git ls-tree
$ git ls-tree -l master
100644 blob c79cad47938a25888a699142ab3cdf764dc99193     162    README.md
100644 blob 86df41b3a8bbfb588e57c7b27742cf312ab3a12a     485    another_pi.c
100644 blob d393b41eb14561e583f1b049db716e35cef326c3     672    math.c

可见,存档内容与指定版本(当前 master 分支的 HEAD)一致。

拓展

除了指定版本,还可以指定从某个子文件夹创建存档文件。例如基于 doc 分支的 Documentation 文件夹,可以创建存档如下:

$ git archive --prefix=docs/ -o docs.zip origin/doc:Documentation
$ git unzip -l docs.zip
Archive:  docs.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2022-01-06 22:37   docs/
       99  2022-01-06 22:37   docs/README.md
      152  2022-01-06 22:37   docs/build.md
---------                     -------
      251                     3 files
# Check content
$ git ls-tree -l origin/doc:Documentation
100644 blob b65b4fc78c0e39b3ff8ea549b7430654d413159f      99    README.md
100644 blob f91777f3e600db73c3ee7b05ea1b7d42efde8881     152    build.md

此外,导出的存档格式也可以指定,如 tartar.gz 等,通过参数 --format=<format> 指定或在 -o 参数后写明导出文件的扩展名即可。以下两个命令是等效的:

$ git archive --format=tar.gz HEAD > offline.tar.gz
$ git archive -o offline.tar.gz HEAD

如果指定的版本不是分支形式,而是一个 committag、或 tree 的 ID,则生成的存档文件略有差别。指定 committag 时,导出为 tar 格式的存档文件会将该 ID 存到一个全局的 pax header 头;而格式为 zip 时,该 ID 会以文件注释的形式呈现。若指定的是 tree 的 ID,存档文件则不会保留任何附加信息。这可以在刚刚演示的两种情况得到验证。打开 offline.zip 文件,可以看到 masterHEAD 头对应的 SHA-1937f9602dcd2236397c916d1ac764efcfa5e97cd)出现在了文件注释位置:

zip file comment

另一方面,以子文件夹 Documentation 导出的存档文件则没有任何显示:

tree ID demo

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安冬的码畜日常

您的鼓励是我持续优质内容的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值