r/git 1d ago

What are your small Git workflow game-changers?

I've been using Git for the better part of a decade, and recently scratched my own itch and built a GUI macOS Git client. I've been trying to keep it simple and lean, basically pulling forward the 80% of what you actually do day-to-day and making that stuff super easy and accessible.

Recently I added a "Squash local commits" feature, mostly because I have a habit of making alot of small commits while developing a feature. But when I ultimately push to my remote (origin) repo, I dont really need all that history. Being able to quickly squash those commits before pushing (especially in a GUI where it's super easy to see exactly what's going to get squashed) has turned out to be a bit of a game-changer for me. Cleaner history, easier to revert, etc.

Which got me wondering, what other small, simple Git workflow game-changers do you all use? Not necessarily big features or complicated workflows, just those little quality-of-life things that once you start using them, you wonder why you weren't doing it all along.

55 Upvotes

48 comments sorted by

31

u/Frum 1d ago

`rerere` is your friend.

I HATE squashing commits. But I do like rebasing often. GitLab refers to my preferred pattern as "semi-linear", and it makes reverting things ALMOST as easy as squash commits.

I also find 3-pane conflict resolution to be drastically superior.

9

u/empire299 1d ago

I love squashing commits - but maybe I make way more than most ppl for a body of work.

3

u/Competitive-Win-9916 1d ago

What’s this mean?

8

u/PM_ME_FIREFLY_QUOTES 1d ago

So its like, premature ejaculation. This guy commits frequently before he's done, but then keeps going and commits repeatedly. I think kids call it gooning these days.

But for git

1

u/Frechetta 8h ago

They're saying they make many commits for a feature.

1

u/snofla 1d ago

Four pane for the win: Perforce diff/merge.

1

u/Storm_Surge 20h ago

Perforce diff/merge can't properly auto-merge two-line changes to a config file half the time. The four panels will never make up for how bad it is at everything else

1

u/snofla 1d ago

Does `rerere` work at scale? (I'm a rebase often guy)

2

u/Frum 13h ago

OMG yes. It's SOOOOOO good.

-6

u/Parasin 1d ago

I agree IMO, you should NEVER alter the git history. Even if that means you have some extra commits in there. Can’t tell you the number of times I have had to cherry pick a small number of changes from one or two commits. Squashing would’ve turned a trivial task into a much more difficult one.

13

u/Soggy_Writing_3912 advanced 1d ago

Squashing withing one's own branch prior to the contents being merged into master/main/trunk is still acceptable.

I don't want my experiments to show up as noise for others in my team and vice versa.

2

u/elephantdingo 1d ago

When someone works on a feature branch they can choose as the “merge strategy” (among other things)

  1. Rebase
  2. Rebase then merge (what OP here is talking about)
  3. Squash

All of these rewrite history to the same degree. So what are you talking about “NEVER alter history” and then say that they should squash?

1

u/StevenJOwens 1h ago

"Rebasing rewrites history. If nobody knows about that history, then that is perfectly fine. If, however, that history is publicly known, then rewriting history in Git works just the way it does in the real world: you need a conspiracy. Conspiracies are really hard keep together, so you better avoid rebasing public branches in the first place." -- Jörg W Mittag

15

u/lorengphd 1d ago

Check out ‘fixup’ and ‘autosquash’. It’s a little shortcut that helps you to squash into a commit that’s not the previous.

Then I constantly use “amend” for just adding recent changes into my last commit.

11

u/xenomachina 1d ago

Check out ‘fixup’ and ‘autosquash’.

git absorb is a nice add-on that will create fix-up commits for you by looking for existing commits that touch the same code. It's nice for when you have a series of commits in your branch, and then make a bunch of small corrections (eg: typo fixes, removing bits of cruft, auto-formatting, etc.). Just:

  1. git add the changes you want to go in.
  2. git absorb to create "fixup" commits
  3. git rebase -i --autosquash main

(You can combine the last two with --and-rebase, if desired.)

3

u/jesusrambo 16h ago

LOVE `git absorb`

12

u/latamakuchi 1d ago

Writing in the commit for a merge conflict resolution how it was solved (what was chosen or if both were combined): makes tracking any issues easier if something is not right later on.

2

u/empire299 1d ago

I like this. All my merges just say “merge” :)

8

u/Alacho 1d ago

Worktrees. They were a gamechanger to me

1

u/MediocreAnalyst2121 2h ago

Something I’ve always wanted to try, but the setting up seems a bot difficult so I’ve never gotten to it

1

u/Alacho 1h ago

It’s one command.

git worktree add ../path/to/where/you/want/it branchPoint

When you are done, git worktree remove ../path/to/where/you/put/it

This is from .git/-location. Always make sure to move out of the git-folder

7

u/aioeu 1d ago edited 1d ago

Git trailers for metadata.

With a bit of Git config and a small shell script, you can use something like:

git commit --trailer=jira:ABC-1234

to automatically add a:

Jira: https://jira.example.com/ABC-1234

trailer to the commit message. You need the script to turn the metadata value into a URL.

(And yes, having a URL is far more user-friendly than just having the issue key alone. It pisses me off when all I've got is a ticket number but no idea which ticket system it's referring to...)

That might seem like a lot of typing, but shell tab-completion can get you to --trailer=jira: with just a couple of key presses.

Bonus: you can have the script automatically determine the issue key from the current branch name (I grab the last branch name component after /) and use that if no value is provided after jira:.

I also occasionally use a --trailer=fixes:<commit> to generate kernel-style:

Fixes: <short-hash> ("<description>")

trailers.

1

u/Dienes16 1d ago

I usually have the ticket number in my branch name, and then a commit-msg hook auto-extracts that and appends it as a trailer in all my commits.

16

u/theclapp 1d ago

Having a private, ignored, git-ignore file, to which you can add all the cruft in your directory that you don't want to commit, but don't want to see constantly in "git status", is nice.

% grep -e core -e exclude .git/config
[core]
excludesfile = .local_gitignore

% grep ignore .local_gitignore
.local_gitignore*

30

u/rom1v 1d ago

There's already the local-equivalent of .gitignore natively: .git/info/exclude

2

u/Cinderhazed15 1d ago

I like to set a user level gitignore file as well for all the stuff I use everywhere, and not manage it per repo…

1

u/ppww 21h ago

That's sensible, but the path above is relative each repository will look for a different file. You don't have to set this config to use a user level ignore file, see the gitignore docs for the default path.

1

u/Cinderhazed15 20h ago

Thats’s what I do, input it in my home directory but it is still relative to each git repo, not relative to where my file is (in ~/.gitignore), from the docs - Patterns which a user wants Git to ignore in all situations (e.g., backup or temporary files generated by the user’s editor of choice) generally go into a file specified bycore.excludesFile in the user’s ~/.gitconfig. Its default value is $XDG_CONFIG_HOME/git/ignore. If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/ignore is used instead.

4

u/fagnerbrack 1d ago

Always commit to main, goes they all environments then straight to prod without any manual gate.

If it breaks then the workflow is not ready and you need to improve your processes and way of working until anyone can push to main without any chance of breaking anything

If you've been there, you know. Continuous Integration 💯

1

u/gautem 1d ago

This is the way!

0

u/kaddkaka 1d ago

So, no reviewing?

Sounds like you don't have any 6 hour tests?

3

u/fagnerbrack 1d ago

Reviewing is all the team working together to do the job. Once it gets to main it has been reviewed by everybody.

This is all documented in the DORA metrics, Google's project Aristotle and Continuous Integration principles

3

u/kaddkaka 1d ago

Aha, now I see, main -> prod without manual interaction. That makes sense.

3

u/Weshmek 1d ago

alias gmb=git merge-base alias gmbfp=git merge-base --fork-point

3

u/Comprehensive_Mud803 21h ago

Using better defaults and aliases.

Better defaults are settings like pull-autostash, pull-rebase, rebase-autostash-autosquash, rerere etc.

Aliases are the shortcuts for often used commands and minor scripts.

Tool-wise it’s been P4merge and Gitup for ages.

Workflow-wise, I’ve tried rebase, merge and squash as standard. In my current team, we agreed on using squash as standard as it simplifies the history a lot.

We also standardized the PR body/squash commit message.

7

u/phileat 1d ago

Using jj instead of git. Rebasing is magical.

1

u/Xavier_OM 1d ago

worktree, fixup commit, merge-base for daily usage

and this series of articles https://devblogs.microsoft.com/oldnewthing/20180323-01/?p=98325 

1

u/lucaprinaorg 1d ago

Git over Reticulum was a game-charger:
https://reticulum.network/manual/git.html

1

u/magic7s 19h ago

GitLab push options:

Push and create a merge request

Push and skip CI

Push and Auto Merge

There are more: https://docs.gitlab.com/topics/git/commit/

1

u/Decent_Carry_3439 17h ago

git worktree was a game-changer for me being able to work on two branches without constantly stashing and switching is surprisingly useful.

1

u/VibrantCanopy 15h ago

```fish function gibdrbm git checkout master and git pull origin and git checkout $argv[1] and git rebase master and git checkout master and git branch -d $argv[1] end

function giprbm set -l branch (git branch --show-current) git checkout master and git pull origin and git checkout $branch and git rebase master end

function git-rename for old_file in $argv[3..-1] set new_file (echo $old_file | perl -pe "s/$argv[1]/$argv[2]/") if test $old_file != $new_file git mv $old_file $new_file end end end ```

0

u/waterkip detached HEAD 1d ago

My own toolkit simplifies a lot of stuf. Aliases, helpers, etc. Reduces typing a lot.

1

u/Soggy_Writing_3912 advanced 1d ago

mine's at https://vraravam.github.io/dotfiles/ - and the aliases are in https://github.com/vraravam/dotfiles/blob/master/files/--XDG_CONFIG_HOME--/git/config (this gets symlinked into the $XDG_CONFIG_HOME/git folder which git uses by default.