This tells you when files in the repository frequently move together. This lets you identify where the coupling is in the system. Coupling is negative and to an extent unavoidable, this tool aims to make it visible.
If every time I commit no file moves at the same time, that's 0 coupling
echo "no-coupling-setup - file_1" > file_1
git add .
git commit --message "demo: no-coupling-setup"
echo "no-coupling-setup - file_2" > file_2
git add .
git commit --message "demo: no-coupling-setup"
When we run git-moves-together we can see that these files have no direct commit based coupling
git-moves-together
0 files move together
If we then make a change to both files in the same commit
echo "coupling-setup - file_1" > file_1
echo "coupling-setup - file_2" > file_2
echo "coupling-setup - file_3" > file_3
git add .
git commit --message "demo: coupling-setup"
When we run git-moves-together we can see that these files have no direct commit based coupling
git-moves-together $PWD
╭──────────────────┬──────────────────┬────────────┬──────────┬─────────╮
│ File A ┆ File B ┆ Together % ┆ Together ┆ Commits │
╞══════════════════╪══════════════════╪════════════╪══════════╪═════════╡
│ some-repo@file_1 ┆ some-repo@file_2 ┆ 50.00% ┆ 1 ┆ 2 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ some-repo@file_1 ┆ some-repo@file_3 ┆ 100.00% ┆ 1 ┆ 1 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ some-repo@file_2 ┆ some-repo@file_3 ┆ 50.00% ┆ 1 ┆ 2 │
╰──────────────────┴──────────────────┴────────────┴──────────┴─────────╯
You can also reduce the commits you're including, by limiting the changes to a specific time period
echo "day-limit-setup - file_1" > file_1
git add .
GIT_COMMITTER_DATE="2005-04-07T22:13:13" git commit --message "demo: day-limit-setup"
git-moves-together -d 30 $PWD
╭──────────────────┬──────────────────┬────────────┬──────────┬─────────╮
│ File A ┆ File B ┆ Together % ┆ Together ┆ Commits │
╞══════════════════╪══════════════════╪════════════╪══════════╪═════════╡
│ some-repo@file_1 ┆ some-repo@file_2 ┆ 50.00% ┆ 1 ┆ 2 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ some-repo@file_1 ┆ some-repo@file_3 ┆ 100.00% ┆ 1 ┆ 1 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ some-repo@file_2 ┆ some-repo@file_3 ┆ 50.00% ┆ 1 ┆ 2 │
╰──────────────────┴──────────────────┴────────────┴──────────┴─────────╯
You can also set a window of time to group by rather than the commit id, which is useful when you're looking for coupling over multiple repositories
Let's make another git repository
echo "time-window-setup - file_1" > "../other-repo/file_1"
echo "time-window-setup - file_2" > "../other-repo/file_2"
echo "time-window-setup - file_3" > "../other-repo/file_3"
git -C "../other-repo" add .
git -C "../other-repo" commit --message "demo: time-window-setup"
echo "time-window-setup - file_1 update" > "../other-repo/file_1"
echo "time-window-setup - file_2 update" > "../other-repo/file_2"
echo "time-window-setup - file_3 update" > "../other-repo/file_3"
git -C "../other-repo" add .
git -C "../other-repo" commit --message "demo: time-window-setup"
Now we can look at the coupling across two repositories
git-moves-together -t 30 "$PWD" "$PWD/../other-repo"
╭───────────────────┬───────────────────┬────────────┬──────────┬─────────╮
│ File A ┆ File B ┆ Together % ┆ Together ┆ Commits │
╞═══════════════════╪═══════════════════╪════════════╪══════════╪═════════╡
│ other-repo@file_1 ┆ other-repo@file_2 ┆ 100.00% ┆ 2 ┆ 2 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_1 ┆ other-repo@file_3 ┆ 100.00% ┆ 2 ┆ 2 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_1 ┆ some-repo@file_1 ┆ 33.33% ┆ 2 ┆ 6 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_1 ┆ some-repo@file_2 ┆ 40.00% ┆ 2 ┆ 5 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_1 ┆ some-repo@file_3 ┆ 40.00% ┆ 2 ┆ 5 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_2 ┆ other-repo@file_3 ┆ 100.00% ┆ 2 ┆ 2 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_2 ┆ some-repo@file_1 ┆ 33.33% ┆ 2 ┆ 6 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_2 ┆ some-repo@file_2 ┆ 40.00% ┆ 2 ┆ 5 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_2 ┆ some-repo@file_3 ┆ 40.00% ┆ 2 ┆ 5 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_3 ┆ some-repo@file_1 ┆ 33.33% ┆ 2 ┆ 6 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_3 ┆ some-repo@file_2 ┆ 40.00% ┆ 2 ┆ 5 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ other-repo@file_3 ┆ some-repo@file_3 ┆ 40.00% ┆ 2 ┆ 5 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ some-repo@file_1 ┆ some-repo@file_2 ┆ 83.33% ┆ 5 ┆ 6 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ some-repo@file_1 ┆ some-repo@file_3 ┆ 83.33% ┆ 5 ┆ 6 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ some-repo@file_2 ┆ some-repo@file_3 ┆ 100.00% ┆ 5 ┆ 5 │
╰───────────────────┴───────────────────┴────────────┴──────────┴─────────╯
Which is why you see the coupling as shown above
git-moves-together -h
Find files that move at the same time in a git repository to identify coupling
Usage: git-moves-together [OPTIONS] [GIT_REPO]...
Arguments:
[GIT_REPO]... A repository to analyse [env: GIT_REPO=] [default: .]
Options:
-d, --from-days <MAX_DAYS_AGO>
Ignore deltas older than the given days [env: MAX_DAYS_AGO=]
-t, --time-window-minutes <TIME_WINDOW_MINUTES>
Group commits by similar time window rather than by commit id [env: TIME_WINDOW_MINUTES=]
-h, --help
Print help
-V, --version
Print version
See the releases page we build for linux and mac, alternatively use brew
brew install PurpleBooth/repo/git-moves-together