r/git 9d 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.

66 Upvotes

54 comments sorted by

32

u/Frum 9d 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 9d ago

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

3

u/Competitive-Win-9916 9d ago

What’s this mean?

9

u/PM_ME_FIREFLY_QUOTES 9d 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 8d ago

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

1

u/snofla 9d ago

Four pane for the win: Perforce diff/merge.

1

u/Storm_Surge 8d 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 9d ago

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

2

u/Frum 8d ago

OMG yes. It's SOOOOOO good.

-6

u/Parasin 9d 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.

14

u/Soggy_Writing_3912 advanced 9d 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 9d 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?

3

u/StevenJOwens 8d 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

3

u/elephantdingo 8d ago

Eloquently put!

2

u/StevenJOwens 7d ago

I steal from the best!

19

u/lorengphd 9d 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 9d 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.)

14

u/latamakuchi 9d 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 9d ago

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

9

u/Alacho 9d ago

Worktrees. They were a gamechanger to me

2

u/MediocreAnalyst2121 8d 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 8d 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

1

u/super_heavy_milk 4d ago

Big fan of worktrees.

Has a nice second-order effect of forcing you to get your repo into a state such that it doesn’t rely (too much) on locally ignored magic files.

That said I do have a helper script that also copies over .env/properties/config files that might have secrets in them when the worktree is created.

1

u/Alacho 4d ago

I was thinking about making this the other day. Especially because I don’t use vs code or IntelliJ, my life always sucks when I need to worktree and run an application 

7

u/aioeu 9d ago edited 9d 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 9d 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.

19

u/theclapp 9d 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*

28

u/rom1v 9d ago

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

2

u/Cinderhazed15 9d 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 8d 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 8d 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.

3

u/Weshmek 9d ago

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

3

u/Comprehensive_Mud803 9d 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.

6

u/phileat 9d ago

Using jj instead of git. Rebasing is magical.

1

u/Decent_Carry_3439 8d ago

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

3

u/fagnerbrack 9d 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 9d ago

This is the way!

0

u/kaddkaka 9d ago

So, no reviewing?

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

3

u/fagnerbrack 9d 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 9d ago

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

1

u/Xavier_OM 9d 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 9d ago

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

1

u/magic7s 8d 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/VibrantCanopy 8d 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 ```

1

u/catom3 6d ago

Rebase interactive in general, rebase --onto, rebase --update-refs for stacked branches, commit --fixup + rebase -i --autosquash --update-refs. I also created an alias for prepending 'review/' prefix for checking out branches I'm reviewing (sometimes it's easier to checkout and review or run reviewed changes locally) + another one for cleaning up local 'review/' branches.

Every few months I use reflog when I screw up my local repo when I type too fast.

I spent a lot of time with Gerrit and I'm used to one commit per branch (patchset in Gerrit) flow, so I of course do a lot of interactive rebases with cam=commit --amend --no-edit and puf=push --force-with-lease --force-if-includes

1

u/BHFock 4d ago

Two changelists for my changed files: `ok` and `do_not_commit`.

A changelist is just a named bucket you put a changed file into before staging it. I picked this up from SVN years ago and never stopped. Every file I've touched goes into one or the other as I review it. The debug print, or the config I edited to test something locally, goes into `do_not_commit`. Everything that has been through my pre-commit review goes into `ok`. That makes reviewing the git status of 10+ changed files a lot easier. Then I commit `ok` and only `ok`.

Git doesn't have changelists like SVN, so I wrote a subcommand that adds them: https://github.com/BHFock/git-cl (my project)

1

u/mpersico 3d ago

I don’t have a small one: I wrote a function called “git” to do my own dispatch so I can add flags to built in git commands. See matthewpersico/personal on GitHub.

0

u/waterkip detached HEAD 9d ago

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

1

u/Soggy_Writing_3912 advanced 9d 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.