This is a small tool that helps to list the files you have changed (added/modified/removed) in your git branch.
The author wrote this tool for a project with very slow tests and tools. A full run took too long for each small change. The author wanted to run the tests and tools only on the files of the current branch.
The tool lists these files:
- the files from the commits since the branch left
origin/main - the files with uncommitted changes
- the untracked files
The tool only prints the list. Send the list to another tool:
$ git-changed -e '**/*.rs' | xargs rustfmtgit diff --name-only $(git merge-base origin/main HEAD)lists the committed and the uncommitted changes. It does not list the untracked files. Addgit ls-files --others --exclude-standardfor those.- lint-staged runs commands on the staged files before a commit. It needs Node.js.
- lefthook is a git hook manager. It gives
{staged_files}and{push_files}to the commands. Alefthookcommand can also callgit-changed. - tj-actions/changed-files lists the changed files in GitHub Actions.
git-changed does not run commands and does not manage hooks. It only lists the files, so you can use it in a terminal, in a hook, or in CI.
Install the tool from crates.io:
$ cargo install git-changedThis project is a Nix flake. It gives you the git-changed package, an overlay and an app.
Run the tool without an installation:
$ nix run github:function-artisans/git-changedAdd the flake to your own configuration:
{
inputs.git-changed.url = "github:function-artisans/git-changed";
}Then take the package for your system:
inputs.git-changed.packages.${system}.defaultOr add the overlay and take pkgs.git-changed:
nixpkgs.overlays = [ inputs.git-changed.overlays.default ];To get the recent changes comparing to the default branch you can type:
$ git-changedIn a subdirectory, the tool prints the paths relative to that directory, like git status. The glob also matches the relative path:
$ cd src
$ git-changed '*.rs' | xargs rustfmtThe tool compares your branch with origin/main. It does not use your local main branch, because that branch can be old.
To use a different base, give the --base option:
$ git-changed --base developmentOr you can set the configuration globally:
$ git config --global changed.defaultBranch developmentOr only for the current repository:
$ git config changed.defaultBranch developmentThe value can be any revision, for example a branch, a tag, or upstream/main.
$ git-changed '**/*.rs'If you need to work with filenames that could contain spaces, then you can change the separator from \n to a NUL character
$ git-changed -0Some tools may not handle files that no longer exist. With this option, you can easily filter out non-existing files, ensuring reliable processing.
$ git-changed -eRun only the specs of the branch. A new spec file is in the list before you run git add:
$ git-changed -e 'spec/**/*_spec.rb' | xargs bundle exec rspecLint the changed files. The -e option removes the deleted files, so the linter does not fail on a missing file:
$ git-changed -e -0 '**/*.py' | xargs -0 ruff checkRun the tests again each time that you save a changed file. entr reads the list of files to watch from standard input:
$ git-changed -e '**/*.rs' | entr -c cargo testOpen all changed files in the editor:
$ vim $(git-changed -e)Select one changed file with fzf and open it:
$ vim "$(git-changed -e | fzf)"Run a linter before each push with lefthook. The list contains all the work on the branch, also the work that you did not commit:
pre-push:
commands:
rubocop:
run: git-changed -e -0 '**/*.rb' | xargs -0 bundle exec rubocopCompare with the development branch and compile each changed file:
$ git-changed -0 -b development '**/*.rs' | xargs -0 -n 1 rustc