有时候我们会把一些构建生成的文件放在版本库中,而这些文件一般比较大,如果放在magit status里面会导致magit卡顿,而多个人协同开发的时候,如果都上传这些文件会导致冲突。
一般对于这样的文件,我们本地希望它被assume unchanged(或者叫做skip worktree)
git提供了两个命令来处理这个需求,一个是 git update-index --skip-worktree -- file
这个功能magit已经添加了对应的实现,但是有一些瑕疵,在子目录的时候只能操作当前目录的文件。
还有一个命令是 git update-index --assume-unchanged -- file
之前一直使用的是 git alias来处理这种情况:
hide = update-index --assume-unchanged
unhide = update-index --no-assume-unchanged
unhide-all = "!git ls-files -v | grep \"^[a-z]\" | awk '{print $2,$NF;}' | xargs git unhide"
hidden = !git ls-files -v | grep \"^[a-z]\"
但是作为一个Emacs党,肯定希望少敲几个字符,一切跟版本控制相关的操作都可以用Emacs来完成。
于是,我写了下面几个函数来处理这种情况,github上面也有人遇到了同样的问题,这里分享一下。
(defun magit-skip-assume-unchanged-files ()
(--keep (and (and (= (aref it 0) ?h)
(substring it 2)))
(magit-git-items "ls-files"
(string-trim
(car (magit-git-items "rev-parse" "--show-toplevel")))
"-v" "--full-name" "-z")))
(defun magit-insert-assume-unchanged-files ()
"Insert a tree of assume unchanged files.
If the first element of `magit-buffer-diff-files' is a
directory, then limit the list to files below that. The value
of that variable can be set using \"D -- DIRECTORY RET g\"."
(when-let ((files (magit-skip-assume-unchanged-files)))
(let* ((base (car magit-buffer-diff-files))
(base (and base (file-directory-p base) base)))
(magit-insert-section (assume-unchanged nil t)
(magit-insert-heading "Assume-unchanged files:")
(magit-insert-files files base)
(insert ?\n)))))
(defun magit-list-all-files ()
(magit-with-toplevel
(with-temp-buffer
(apply #'magit-git-insert '("ls-files" "-z" "--full-name"))
(split-string (buffer-string) "\0" t))))
(defun magit-assume-unchanged (file)
"Call \"git update-index --assume-unchanged FILE\"."
(interactive (list (magit-read-file-choice "Assume unchanged for: "
(cl-set-difference
(magit-list-all-files)
(magit-skip-assume-unchanged-files)))))
(magit-with-toplevel
(magit-run-git "update-index" "--assume-unchanged" "--" file)))
(defun magit-no-assume-unchanged (file)
"Call \"git update-index --no-assume-unchanged FILE\"."
(interactive (list (magit-read-file-choice "Do not assume unchanged for: "
(magit-skip-assume-unchanged-files))))
(magit-with-toplevel
(magit-run-git "update-index" "--no-assume-unchanged" "--" file)))
Add assume-unchanged section to magit-status buffer:
(magit-add-section-hook 'magit-status-sections-hook
'magit-insert-assume-unchanged-files nil t)
;; define jump
(magit-define-section-jumper magit-jump-to-assume-unchanged "Assume-unchanged files" assume-unchanged)
(define-key magit-status-mode-map "ga" 'magit-jump-to-assume-unchanged)