【Git 学习笔记_11】第五章 在 Git 仓库存入附加信息(上)

avatar
作者
筋斗云
阅读量:2

第五章 在 Git 仓库存入附加信息

相关主题

  • 添加第一条 Git 笔记
  • 按类别区分 Git 笔记
  • 从远程库读取 Git 笔记
  • 推送 Git 笔记到远程库
  • commit 版本添加标签

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 +0100      Prepare post 3.2.0 builds      Change-Id: Ie2bfdee0c492e3d61d92acb04c5bef641f5f132f     Signed-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)、编辑(editgit 笔记:

# 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 version      erified 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

小结

  1. git notes edit -m 的用法已被淘汰,Git 推荐使用 git notes add 来替换 git notes edit
  2. 决定 commit 哈希值的三个因素:
    1. 版本内容(the content in the commit)
    2. 父级版本(the parents of the commit)
    3. 提交信息(the commit message)

5.2 按类别区分 Git 笔记

正如上一节提到的,git 笔记本质上是一个命名空间为 refs/notes/ 的引用,默认展示在 git log 中的是 refs/notes/commits 引用。此外还可以自定义笔记类别,如 featureImplementeddefectalsoCherryPick 等等,以便对笔记统一归类管理。

本例的演示场景:假设在项目中修正了一个缺陷(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 note1  Notes (alsoCherrypick):     570bba5  Notes (defect):     Bug:24435 

小结

  1. 添加 git notes 默认归类到 refs/notes/commits,可随 git log 一并展示;
  2. 如果使用 git log --oneline,则显示对应的 git notes 需要带 --notes 标记;
  3. git log 显示自定义类型的 notes,有两种方式:
    1. git log 后加 --notes=<categoryName>
    2. 修改 git 配置项:git config notes.displayRef 'refs/notes/<catName>'git config notes.displayRef 'refs/notes/*'

拓展

签出分支时,联想到 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 时,该目录就有相同数量的文件),只能删除分支后重新签出。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!