第五章 在 Git
仓库存入附加信息
相关主题
Git
最强大的一个特性,在于它的提交历史 永不可改变。这意味着任何试图篡改仓库历史的行为,对于其他克隆该仓库的人来说 都是可见的。这一特性也给开发者带来些许困扰,尤其是需要在已经发布的提交记录中修改版本注释信息的时候。正是由于 git
历史的不可变更性,git
笔记(notes
)才应运而生。本质上,git
笔记是 refs/notes/commits
引用的附加版。笔记内容既可以在执行 git log
命令时,随提交信息一同展示出来,也可以发布到远程仓库供其他人获取笔记。
5.1. 添加第一条 Git
笔记
本节将在已发布的版本中添加附加信息。如果直接修改目标版本,则 commit
的哈希值也会变动。以 jgit
库为例,先演示直接修改历史版本的效果,再给出使用 git
笔记的演示方案。
# Clone repo
$ git clone https://git.eclipse.org/r/jgit/jgit chapter5
$ cd chapter5
# Checkout a new branch based on stable-3.2
$ git checkout -b notesMessage --track origin/stable-3.2
# Check HEAD hash: f839d383e6fbbda26729db7fd57fc917fa47db44
$ git log -1
# Edit commit message, add 'Update MANIFEST files'
$ git commit --amend
# Check HEAD hash: f942f7b58238b5aaac566038a7d67e0cb6a02fe1
# commit hash diverged
$ git log -1
# See the change via status
$ git status
# via gitk
$ gitk origin/stable-3.2 HEAD
结果如下:(版本结构已发生变化)
这时使用 git notes
就可避免:
# Resume
$ git reset --hard origin/stable-3.2
# Add a git note
$ git notes add -m 'Update MANIFEST files'
# Check git log (f839d383e6fbbda26729db7fd57fc917fa47db44)
$ git log -1
commit f839d383e6fbbda26729db7fd57fc917fa47db44 (HEAD -> notesMessage, origin/stable-3.2)
Author: Matthias Sohn <matthias.sohn@sap.com>
Date: Wed Dec 18 21:16:13 2013 +0100Prepare post 3.2.0 buildsChange-Id: Ie2bfdee0c492e3d61d92acb04c5bef641f5f132fSigned-off-by: Matthias Sohn <matthias.sohn@sap.com>Notes:Update MANIFEST files
# Check status (not diverged)
$ git status
# (No changes)
虽然 git notes
没有在原记录上直接修改(像 --amend
那样),但也实现了对历史提交信息进行增补,且不影响原有的树形版本结构。
拓展
除了通过 git notes add
新增一个 git
笔记,还可以强制替换(-f
)、追加(append
)、编辑(edit
)git
笔记:
# force to add notes (replace the old one)
$ git notes add -f -m "Update MANIFESTS files for next version"
# append content to a note
$ git notes append -m "Verified by John Doe"
# Show in the log via --notes
$ git log --oneline --notes
f839d383e (HEAD -> notesMessage, origin/stable-3.2) Prepare post 3.2.0 builds
Notes:Update MANIFESTS files for next versionerified by John Doe# Edit a note (this would replace the old note with 'John Doe')
$ git notes edit -m 'John Doe'
The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.
Please use 'git notes add -f -m/-F/-c/-C' instead.
# git notes edit without any arguments would be the same as git notes add
$ git log --oneline --notes -1
f839d383e (HEAD -> notesMessage, origin/stable-3.2) Prepare post 3.2.0 builds
Notes:John Doe
更多子命令,详见 git help notes
。
小结
5.2 按类别区分 Git
笔记
正如上一节提到的,git 笔记本质上是一个命名空间为 refs/notes/
的引用,默认展示在 git log
中的是 refs/notes/commits
引用。此外还可以自定义笔记类别,如 featureImplemented
、defect
、alsoCherryPick
等等,以便对笔记统一归类管理。
本例的演示场景:假设在项目中修正了一个缺陷(defect
),产生了一个 commit
版本,同时还对受该缺陷影响的其他版本做了同步修复。示例将新建一个 git
笔记类型 refs/notes/alsoCherryPick
,用来说明当前版本如果要被 cherry-pick
到其他分支,那么应该同时将 alsoCherryPick
中提到的相关 commit
版本一并带上,因为它们都是对同一缺陷的修复。
# Checkout new branch
$ git checkout -b notesReferences --track origin/stable-3.1
# List commits for use
$ git log -10 --oneline
da6e87bc3 (HEAD -> notesReferences, origin/stable-3.1) Prepare post 3.1.0 builds
16ca725b3 (tag: v3.1.0.201310021548-r) JGit v3.1.0.201310021548-r
c6aba9966 Fix order of commits in rebase todo file header
5a2a2222e Prepare post 3.1.0 RC1 builds
6f0681eb9 (tag: v3.1.0.201309270735-rc1) JGit v3.1.0.201309270735-rc1
a065a06c2 Attempt to fix graph layout when new heads are introduced
b4f07df35 Prepare re-signing pgm's ueberjar to avoid SecurityException
aa4bbc67b Use full branch name when getting ref in BranchTrackingStatus
570bba5e7 Ignore bitmap indexes that do not match the pack checksum
801aac579 Merge branch 'stable-3.0'# Add notes for current HEAD
$ git notes add -m "test note"
# Select a commit (570bba5) categoried as alsoCherrypick
$ git notes --ref alsoCherryPick add -m "570bba5" b4f07df
# Check in the log view with --notes
$ git log -1 b4f07df --notes=alsoCherryPick
# config the alsoCherryPick notes' reference by default
$ git config notes.displayRef "refs/notes/alsoCherryPick"
# config to show all notes with all categories
$ git config notes.displayRef 'refs/notes/*'
# Test to add a new note with category of 'defect'
$ git notes --ref defect add -m "Bug:24435" b4f07df
# Check to see whether or not defect content is displayed
$ git log -1 b4f07df --oneline --notes
b4f07df35 Prepare re-signing pgm's ueberjar to avoid SecurityException
Notes:test note1Notes (alsoCherrypick):570bba5Notes (defect):Bug:24435
小结
拓展
签出分支时,联想到 git
笔记引用与其他远程跟踪分支引用的相似性,可以在本地直接签出 refs/notes
分支:
$ git checkout -b myNotes notes/alsoCherryPick
Switched to a new branch 'myNotes'
$ ls
b4f07df357fccdff891df2a4fa5c5bd9e83b4a4a
$ cat b4f07df357fccdff891df2a4fa5c5bd9e83b4a4a
570bba5
可见,将 notes
引用作远程跟踪分支时,该分支下的文件,其文件名为指定类别的 notes
所指向的目标 commit
的哈希值,文件内容为 git
笔记内容。
值得一提的是,经实测,签出某个 notes
引用后,对应的分支并不会自动更新该引用下的文件列表(当有多个同一类别的 note
时,该目录就有相同数量的文件),只能删除分支后重新签出。