[求助]magit 处理 gpg 文件: diff、merge

使用场景

  • 使用org文件记录各种用户名+密码,使用GnuPG加密org文件,文件后缀为 .org.gpg
  • 使用emacs打开gpg文件时自动引导输入密码进行解密,保存时自动加密。
  • gpg文件加入git版本管理

困扰

  • 在不同的pc上编辑gpg文件,在push的时候才发现没有和仓库同步,导致冲突由于是二进制文件,无法通过magit进行 diff/merge操作。
  • 在此请教各位的解决方案(如有,后文可忽略)

尝试解决方案

  • diff:
    • git diff:通过以下配置可以实现 git diff,但在magit中 ediff-diff-program 仍然是 diff,不能处理 gpg 文件

      git config --global diff.gpg.textconv “gpg --no-tty --decrypt”

    • ediff:追踪找到ediff-make-temp-file函数,添加了伪分隔线后面的部分。

      • 通过判断 buffer名,将临时文件重命名为gpg文件
      • 使用 find-file 重新解密
      • 保存解密后的明文,返回明文临时文件,提供给 ediff-diff-program使用

      目前此方法遇到的问题是:如果将工作区的文件与历史版本进行比较,工作区密文文件对应的buffer会被替换成明文临时文件的buffer,不能使用ediff进行merge

(with-eval-after-load 'ediff
 (defun ediff-make-temp-file (buff &optional prefix given-file start end)
   (let* ((p (ediff-convert-standard-filename (or prefix "ediff")))
          (short-p p)
          (coding-system-for-write ediff-coding-system-for-write)
          f short-f)
     (if (and (fboundp 'msdos-long-file-names)
              (not (msdos-long-file-names))
              (> (length p) 2))
         (setq short-p (substring p 0 2)))

     (setq f (concat ediff-temp-file-prefix p)
           short-f (concat ediff-temp-file-prefix short-p)
           f (cond (given-file)
                   ((find-file-name-handler f 'insert-file-contents)
                    ;; to thwart file handlers in write-region, e.g., if file
                    ;; name ends with .Z or .gz
                    ;; This is needed so that patches produced by ediff will
                    ;; have more meaningful names
                    (ediff-make-empty-tmp-file short-f))
                   (prefix
                    ;; Prefix is most often the same as the file name for the
                    ;; variant.  Here we are trying to use the original file
                    ;; name but in the temp directory.
                    (ediff-make-empty-tmp-file f 'keep-name))
                   (t
                    ;; If don't care about name, add some random stuff
                    ;; to proposed file name.
                    (ediff-make-empty-tmp-file short-f))))

     ;; create the file
     (ediff-with-current-buffer buff
       (write-region (if start start (point-min))
                     (if end end (point-max))
                     f
                     nil          ; don't append---erase
                     'no-message)
       (set-file-modes f ediff-temp-file-mode)
       (expand-file-name f))
;--------------------------------------------------------------------------------------
     (if (string-match "org.gpg" (buffer-name buff))
         (if (string-match "org.gpg$" (buffer-name buff))
             (progn ;; file has been decoded, write buffer's conntent to
               (let* ((f (ediff-make-empty-tmp-file short-f)))
                 (get-buffer-create "*New-decode*")
                 (switch-to-buffer buff)
                 (append-to-buffer "*New-decode*" (point-min) (point-max))
                 (write-file f nil)
                 (kill-buffer (get-buffer "*New-decode*"))
                 (expand-file-name f)
                 ))
           (with-current-buffer buff
             (read-only-mode 0)
             (erase-buffer)
             (let* ((f-gpg (format "%s.org.gpg" f))
                    (buff-decode (format "%s.gpg" (file-name-base f-gpg)))
                    (file-decode (file-name-sans-extension f-gpg)))
               (rename-file f f-gpg)
               (find-file f-gpg)
               (delete-file f-gpg)
               (recentf-remove-if-non-kept f-gpg)
               (write-file file-decode nil)
               (append-to-buffer buff (point-min) (point-max))
               (kill-buffer (get-buffer buff-decode))
               (switch-to-buffer buff)
               (expand-file-name file-decode))))
       (expand-file-name f))
     )))
1 个赞

印象中, doom emacs 有个 pass, 是专门解决这个应用问题的.

我现在也碰到了一样的问题,不过还没来得及折腾😂️

使用org文件记录各种用户名+密码,使用GnuPG加密org文件,文件后缀为 .org.gpg。

我用的pass,也是文本文件加密

使用emacs打开gpg文件时自动引导输入密码进行解密,保存时自动加密。

参见 https://emacs.stackexchange.com/a/32882

gpg文件加入git版本管理

git config --global diff.gpg.textconv "gpg --no-tty --decrypt"
echo "*.gpg filter=gpg diff=gpg" > .gitattributes
echo "*.gpg filter=gpg diff=gpg" > .gitattributes

这个会不让git把 .gpg 当二进制文件

1 个赞

谢谢提醒,空了去抄抄学习一下

谢谢补充,这个设置前面漏写了

学到了,没想到 git 还能支持解析 gpg 文件,过两天我就整理下发到 EmacsTalk 公众号😁

填坑了

https://emacstalk.github.io/post/011/

3 个赞