Here's how I address this problem.

When I'm developing, but before I create a PR, I'll create a bunch of stream-of-consciousness commits. This is stuff like "Fix typo" or "Minor formatting changes" mixed in with actual functional changes.

Right before I create the PR, or push up a shared branch, I do an interactive rebase (git rebase -i).

This allows me to organize my commits. I can squash commits, amend commits, move commits around, rewrite the commit messages, etc.

Eventually I end up with the 2-4 clean commits that your coworkers have. Often I design my commits around "cherry-pick" suitability. The commit might not be able to stand on its own in a PR, but does it represent some reasonably contained portion of the work that could be cherry-picked onto another branch if needed?

Granted, all of the advice above requires you to adhere to a "prefer rebase over merge" workflow, and that has some potential pitfalls, e.g. you need to be aware of the Golden Rule of Rebasing:

https://www.atlassian.com/git/tutorials/merging-vs-rebasing#...

But I vastly prefer this workflow to both "merge only," where you can never get rid of those stream-of-consciousness commits, and "squash everything," where every PR ends up with a single commit, even if it would be more useful to have multiple commits that could be potentially cherry-picked.

The only problem I have with this workflow in the command line is that I would like to be able to split changes to the same file across multiple commits. I think some GUI tools enable this, anyone know about it?

Have a look at `tig`. It's even included in Git for Windows now and does this reasonably well.

Only the keybindings are a bit weird if you're not accustomed to Vim bindings:

- Open tig

- Change into the staging view with `s`

- Select your file using the arrow or `j` and `k` keys

- Press Return to show the diff

- Navigate to the line(s) in question with `j` and `k` (arrow keys will switch files)

- Stage parts with `1` (single line), `2` (chunk parts), `u` (chunks) or split chunks with `\`

- "Leave" the diff with `q`

- You can find the keybindings with `h` in the help screen, which also uses Vim keys -- like manpages usually do

I used tig for a bit because it was the nicest way I could find to do line-level staging in a terminal. But was really impressed with gitui https://github.com/extrawurst/gitui so I've switched to that