Skip to content

Spot coupling by finding out which files are always in the same commit

License

Notifications You must be signed in to change notification settings

PurpleBooth/git-moves-together

Repository files navigation

git moves-together

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.

Getting Started

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

Usage

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

Installing

See the releases page we build for linux and mac (all x86_64), alternatively use brew

brew install PurpleBooth/repo/git-moves-together