31

Is there a way to list only the directories that were changed?

If I'm at the git root say, ~/project

Files I changed are

~/project/subtool/file1

~/project/subtool/file2

~/project/subtool3/file1

I just want

~/project/subtool

~/project/subtool3

0

5 Answers 5

42

You could use git-diff with the --dirstat parameter.

In your scenario, let's say you have the following commit:

$ git diff --name-status HEAD~1
M       subtool/file1
M       subtool/file2
M       subtool3/file1

It would produce the following output:

$ git diff --dirstat=files,0 HEAD~1
  66.6% subtool/
  33.3% subtool3/

Make sure to add ,0, otherwise git diff will by default only show directories with at least 3% changes. I also chose files as this is the computationally cheapest option and you do not seem to care about specific changes anyway.

If you are able to use sed you can get rid of the percentage values (you may want to tweak the regular expression a bit to fit your needs):

$ git diff --dirstat=files,0 HEAD~1 | sed 's/^[ 0-9.]\+% //g'
subtool/
subtool3/
Sign up to request clarification or add additional context in comments.

9 Comments

This is pretty perfect! Is there anyway to avoid outputting the % details though? I wanna read the directories into a script and use that for something:wq
If you're scripting it, git diff-tree is built for that. doit() { git diff-tree "$@" | awk '$1$2~/04/' | cut -f2-; }
The sed regular expression didn't work for me on macOS. BSD sed with man dated May 10, 2005.
On macOS in zsh shell I had to add the -E flag to the sed command and remove the forward slash from \+. This is what I used: sed -E 's/^[ 0-9.]+% //g'
By piping the output to another sed command, you can remove all the sub-folder names so you only have the top-level folders. git diff --dirstat=files,0 HEAD~1 | sed -E 's/^[ 0-9.]+% //g' | sed -E 's/\/.*$//g'
|
11

this solution works also for files in the root directory:

git diff --name-only HEAD~1 | awk -F "/*[^/]*/*$" '{ print ($1 == "" ? "." : $1); }' | sort | uniq

Changes in root directory will be listed as .

The limitation of git diff --dirstat=files,0 HEAD~1 is that it doesn't show changes in the root directory.

2 Comments

this producing somewhat duplicates. If I have dir/foo/file-a it shows dir and dir/foo
@TheFool I added my answer in here by doing an update to Lari Hotari 's answer You can find it here: stackoverflow.com/a/72781954/11784338
9

Here's an alternative using xargs and dirname instead of anything like sed or awk.

git diff HEAD~1 --name-only | xargs dirname | sort | uniq
  1. git diff … will list modified file paths.
  2. | xargs dirname will convert file paths into dir paths.
  3. | sort | uniq will remove duplicates.

Note that this will produce a . line if you modified any files in your repo root directory.

Comments

0

After adding split and uniq option from @Lari Hotari answer. One can get unique directories that are modified.

$(git diff --name-only HEAD~1 | awk -F "/*[^/]*/*$" '{ print ($1 == "" ? "." : $1); }' | cut -d "/" -f 1 | sort | uniq)

What this command does?

  • First it finds all the modified files and return the parent directory of the changed files @Lari Hotari [answer][1]
  • The next part is where it splits using '/' and return first element in string array i.e., Root directory of the changed file.

This command will monitor all the changes of sub-projects in monorepo and can install dependencies only for the changed workspaces using npm i -ws command

3 Comments

For that, you don't even need awk: git diff --name-only | cut -d/ -f1 | uniq gives you also the root dir of changed modules.
Yes, But in my mind I wanted only root directories not files so added this step after awk. As I was working on installing specific workspaces thing right now
yes, as I said, you get only directories with that command. The cut is doing that. Not awk. You can drop the awk part completely.
-2

Use git diff with parameter --dirstat, e.g.

git diff --dirstat HEAD~100..HEAD

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.