Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code churn per file #17

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,5 @@ venv.bak/

# mypy
.mypy_cache/

.vscode
98 changes: 94 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# True Git Code Churn

![GitHub release version](https://img.shields.io/github/v/release/flacle/truegitcodechurn.svg?sort=semver)

A Python script to compute "true" code churn of a Git repository. Useful for software teams to openly help manage technical debt.
Expand All @@ -13,44 +14,133 @@ Solutions that I've found online looked at changes to files irrespective whether

*Tested with Python version 3.5.3 and Git version 2.20.1*

# How it works
## How it works

This lightweight script looks at commits per author for a given date range on the **current branch**. For each commit it bookkeeps the files that were changed along with the LOC for each file. LOC are kept in a sparse structure and changes per LOC are taken into account as the program loops. When a change to the same LOC is detected it updates this separately to bookkeep the true code churn.
Result is a print with aggregated contribution and churn per author for a given period in time.

***Note:*** This includes the `--no-merges` flag as it assumes that merge commits with or without merge conflicts are not indicative of churn.

# Usage
Positional (required) arguments:
## Usage

### Positional (required) arguments

- **after**        after a certain date, in YYYY[-MM[-DD]] format
- **before**     before a certain date, in YYYY[-MM[-DD]] format
- **author**     author string (not a committer), leave blank to scope all authors
- **dir**            include Git repository directory

Optional arguments:
### Optional arguments

- **-h, --h, --help**    show this help message and exit
- **-exdir**                   exclude Git repository subdirectory
-- **--show-file-data** display line count changes per file

## Usage Example 1

```bash
python ./gitcodechurn.py after="2018-11-29" before="2019-03-01" author="an author" dir="/Users/myname/myrepo" -exdir="excluded-directory"
```

## Output 1

```bash
author: an author
contribution: 844
churn: -28
```

## Usage Example 2

```bash
python ./gitcodechurn.py after="2018-11-29" before="2019-03-01" author="" dir="/Users/myname/myrepo" -exdir="excluded-directory"
```

## Output 2

```bash
authors: author1, author2, author3
contribution: 4423
churn: -543
```

## Usage Example 3

```bash
python ./gitcodechurn.py after="2018-11-29" before="2021-11-05" author="flacle" dir="/Users/myname/myrepo" --show-file-data
```

## Output 3

```bash
author: flacle
contribution: 337
churn: -19
-------------------------------------------------------------------------------
FILE NAME | LINE # | ADDED | REMOVED
-------------------------------------------------------------------------------
gitcodechurn.py | 1 | 190 | 0
-------------------------------------------------------------------------------
gitcodechurn.py | 2 | 4 | 0
-------------------------------------------------------------------------------
gitcodechurn.py | 37 | 2 | 0
-------------------------------------------------------------------------------
gitcodechurn.py | 40 | 0 | 1
-------------------------------------------------------------------------------
gitcodechurn.py | 42 | 1 | 0
-------------------------------------------------------------------------------
gitcodechurn.py | 45 | 0 | 1
-------------------------------------------------------------------------------
gitcodechurn.py | 47 | 1 | 0
-------------------------------------------------------------------------------
gitcodechurn.py | 50 | 0 | 1
-------------------------------------------------------------------------------
gitcodechurn.py | 52 | 1 | 0
-------------------------------------------------------------------------------
gitcodechurn.py | 55 | 0 | 1
-------------------------------------------------------------------------------
gitcodechurn.py | 57 | 8 | 1
-------------------------------------------------------------------------------
gitcodechurn.py | 66 | 2 | 0
-------------------------------------------------------------------------------
gitcodechurn.py | 62 | 0 | 1
...
-------------------------------------------------------------------------------
gitcodechurn.py | 200 | 1 | 0
-------------------------------------------------------------------------------
README.md | 12 | 2 | 0
-------------------------------------------------------------------------------
README.md | 16 | 0 | 1
-------------------------------------------------------------------------------
README.md | 18 | 1 | 0
-------------------------------------------------------------------------------
README.md | 21 | 11 | 0
-------------------------------------------------------------------------------
README.md | 20 | 0 | 1
-------------------------------------------------------------------------------
README.md | 33 | 1 | 0
-------------------------------------------------------------------------------
README.md | 22 | 0 | 1
-------------------------------------------------------------------------------
README.md | 35 | 1 | 0
-------------------------------------------------------------------------------
README.md | 24 | 0 | 2
-------------------------------------------------------------------------------
README.md | 37 | 3 | 0
-------------------------------------------------------------------------------
README.md | 41 | 12 | 0
```

Outputs of Usage Example 1 can be used as part of a pipeline that generates bar charts for reports:
![contribution vs churn example chart](/chart.png)

## How to contribute

At this time, the code is organized into a script which can be located at `gitcodechurn.py`. There is [an open issue](https://github.com/flacle/truegitcodechurn/issues/9) to conver this repository
into a more formal Object Oriented structure.

For now the code is located in `gitcodechurn.py` and the tests are located in `test_gitcodechurn.py`. To test, kindly ensure `pytest` and `pytest-mock` are installed. Then, in project root run

```bash
pytest
```
Loading