4

Is there a way to provide a list of files that have been edited since a previous commit or branch with helm and projectile integration?

The use case is as follows:

  1. Create feature branch feat-my-thing off of master.
  2. Modify foo.txt and bar.txt
  3. Commit changes.
  4. Days pass. Work on other things.
  5. Revisit feat-my-thing branch.
  6. I'd really like to select from a list of just foo.txt or bar.txt as those are the only files with changes since master.

For small repos, helm-projectile-find-file works well because I can usually remember what I was working on. With hundreds of files, is not as helpful especially because I'm usually only concerned with 1-5 files for a feature branch.

Joe
  • 1,312
  • 1
  • 8
  • 19

1 Answers1

3

Here's a complete working solution with an example keybinding for spacemacs. The master branch is hard-coded in as the default branch to compare for file changes against. If you want to diff against the nearest parent branch you would need something like this from https://stackoverflow.com/questions/10641361

git diff --name-only <notMainDev> $(git merge-base <notMainDev> <mainDev>)

Emacs Code. This is mostly a simplification of helm-projectile-find-files and the resulting calls into projectile-current-project-files and projectile-dir-files

(defun my:helm-projectile-changed-master ()
  "Finds files changed from master in the current project."
  (interactive)
  (let ((changed-files (my:project-files-changed-from-master)))
    (if changed-files
        (helm :sources (helm-projectile-build-dwim-source changed-files)
              :buffer "*helm projectile*"
              :prompt (projectile-prepend-project-name "Find file: "))
      (message "No files have changed from master."))))

(defun my:project-files-changed-from-master ()
  "Returns a list of files changed from master in the current project."
  (cl-mapcan
  #'my:get-files-changed-from-master-in-dir
  (projectile-get-project-directories)))

(defun my:get-files-changed-from-master-in-dir (directory)
  "Returns list of files changed from master branch in DIRECTORY."
  (let* ((root (projectile-project-root))
        (default-directory directory)
        (command "git diff --name-only master")
        (changed-files (split-string
                        (projectile-shell-command-to-string command)
                        "\n"))
        (changed-files-no-empty (delete "" changed-files))
        (get-relative-project-file-name
          (lambda (file)
            (file-relative-name (expand-file-name file directory)
                                root))))
    (projectile-adjust-files
    (mapcar get-relative-project-file-name
            changed-files-no-empty))))

(spacemacs/set-leader-keys "pj" #'my:helm-projectile-changed-master)
Joe
  • 1,312
  • 1
  • 8
  • 19