One of Julia’s superpowers is throwing questions like this out into the fediverse and collating the interesting responses into informative articles.
Not everything is an article, because not everything produces good responses, and sometimes the signal is drowning in noise (people can be so fucking awful). One of the reasons I like following Julia on Mastadon is to learn what that process looks like, and how she tries to preempt bad responses. If that sounds interesting to you, follow her!
Makes it nicer to copy, paste and write out, and git will always use the ssh URLs.
It also makes the URLs you see more consistent with the web UI which is also a plus for copying.
If you use submodules, these are not nice to have, they’re absolutely essential. Without them, you can’t have a submodule that you can push to but non-logged-in users can clone.
Tracking upstreams that you don’t control. Tracking clones of upstream with some patches. Handling multiple modules that are loosely coupled and where people working on one do not need to clone the others.
If they also use this option because they want the same for their own GitHub projects, does their insteadOf not also trigger for the submodules in your project?
If they’re using this option, then they have a GitHub account with ssh credentials on the machine they’re using for checkouts and so it will work fine for them. Every logged in GitHub user has, at a minimum, read access to all public repos. It’s more polite to use the https repo in submodules though, because then that also works for not logged in users. This also avoids needing to provision CI systems with GitHub credentials and so on.
One option I love and don’t think is very well-known is blame.ignoreRevsFile. It can filter out “noise” in git blame.
I set this one up early last year for my team. Someone almost 10 years ago made a massive commit that only modified whitespace (making indentation consistent). This made the git blame useless for all the lines it modified.
I added the hash of that commit to a .git-blame-ignore-revs file in our repo, and ensured everyone runs git config blame.ignoreRevsFile .git-blame-ignore-revs when setting up the dev environment. Now the blame skips that commit and we can more easily see why those lines were added or changed.
You can use git blame -w for this that ignores whitespaces. For code movements you can use -C (stacks multiple times).
But thx, didn’t know ignore-revs
I use format.signature to replace the git version on patches produced with git-format-patch. Makes no functional differences and you can self-express using an entire new medium!
[format]
signature = "Bananas"
So instead of say
--
2.42
your patch now ends with
--
Bananas
To preserve commit notes when recreating refs:
[notes "rewrite"]
amend = true
rebase = true
To never abbreviate the commit SHA in git-log:
[log]
abbrevCommit = false
To remove a/ and b/ from diffs so that you can copy paste them like a person whose humanity is respected:
I’ve ended up disabling diff.noprefix as it definitely caused issues with being able to do git format-patch / git apply but +1 it as being super useful!
Heh – while reading this I thought that sounded like a nice thing to turn on, but had then quickly had exact same concern. However, after testing it out it looks like in recent versions of git (somewhere between 2.34 and 2.43, not sure offhand exactly when) format-patch has been fixed to override that setting and always include the a/b prefixes.
Things I have in my .gitconfig which weren’t mentioned:
diff.renames = copies makes git diff detect copies better
diff.mnemonicprefx = true this changes a/ and b/ depending on what you compare. I don’t really notice it that much.
diff.algorithm = patience better diffs
branch.autoSetupRebase = always automatically sets the upstream of new branches to the branch you based it on.
rebase.abbreviateCommands = true makes interactive rebase commands one letter. This is probably mandatory if you rebase enough.
init.defaultBranch = master ;)
alias.fixes = show -s '--pretty=format:%h (\"%s\")'. This prints the short hash and summary like a8dc4965f09 ("clk: clk-gpio: add actual gated clock") for use in Fixes: tags or commit messages.
advice.detachedHead = false suppresses the useless warning message about detached heads.
Depending on the project, I also have
submodule.recurse = true makes things like git grep recurse into submodules by default. This is super handy if you have a bunch of submodules since you can easily search the whole project.
diff.submodule = log shows the log of commits added in submodules. This is a lot more useful than the default IMO.
Does your editor have a built-in single-key binding for “replace the current word with a single letter”? In Vim, replacing one letter with a different letter is two keystrokes (e.g. rf) but I can’t think of a way to replace a multi-character word with one letter in fewer than four keystrokes (cwf^[).
Nope, but four keystrokes really isn’t an issue compared to 2, it’s just 2 characters.
I thought it would matter much greater if you needed to backspace a few more times, but yes, you do save at least 2 characters even with modal editors.
Oh, OK. I don’t think I’ve ever found deleting a single letter any easier or harder than deleting a word - but I guess everyone uses editors in different ways. Thanks!
I put ff = only on merge rather than pull, this way it affects both pull and every other merge operation, making it much cleaner.
Non-ff merges can still be created using --no-ff.
push.default simple, push.default current
I prefer upstream, this way it only pushes to the branch configured as the current’s upstream. No name matching, explicit configuration.
The one major drawback is it requires religiously creating feature branches with --no-track to avoid tracking the base branch. Disabling tracking can be set globally, but then it’s a pain in the ass when you’re actually trying to create tracking branches for upstream’s.
Other config items I have:
log.decorate true, adds refs matching the commits to the log, useful to get a quick overview of how far ahead you are, or of stacked branches
fetch.parallel 0 allows running concurrent fetches, mostly useful when there are multiple remotes or submodules being fetched at the same time, otherwise fetches are sequential
receive.autogc false and receive.unpackLimit 1 can make fetching complete faster as git will never bother unpacking objects on fetch, and will not try to immediately run a GC
One of Julia’s superpowers is throwing questions like this out into the fediverse and collating the interesting responses into informative articles.
Not everything is an article, because not everything produces good responses, and sometimes the signal is drowning in noise (people can be so fucking awful). One of the reasons I like following Julia on Mastadon is to learn what that process looks like, and how she tries to preempt bad responses. If that sounds interesting to you, follow her!
I put some of my favorite Git options here: https://bernsteinbear.com/git/
I think
git recentis the one I use the most, especially when context switching a lot.git-absorb is a must-have. Needs some fixups on its CLI, but otherwise does exactly what you want it to do.
That’s worth submitting on its own.
Feel free! I think I submit too much of my own stuff
My favourite option has got to be these:
Makes it nicer to copy, paste and write out, and git will always use the ssh URLs. It also makes the URLs you see more consistent with the web UI which is also a plus for copying.
If you use submodules, these are not nice to have, they’re absolutely essential. Without them, you can’t have a submodule that you can push to but non-logged-in users can clone.
Aaah, git submodules are such a headache. What are they even actually useful for?
Tracking upstreams that you don’t control. Tracking clones of upstream with some patches. Handling multiple modules that are loosely coupled and where people working on one do not need to clone the others.
If they also use this option because they want the same for their own GitHub projects, does their
insteadOfnot also trigger for the submodules in your project?If they’re using this option, then they have a GitHub account with ssh credentials on the machine they’re using for checkouts and so it will work fine for them. Every logged in GitHub user has, at a minimum, read access to all public repos. It’s more polite to use the https repo in submodules though, because then that also works for not logged in users. This also avoids needing to provision CI systems with GitHub credentials and so on.
None of this applies to private repos, of course.
One option I love and don’t think is very well-known is
blame.ignoreRevsFile. It can filter out “noise” in git blame.I set this one up early last year for my team. Someone almost 10 years ago made a massive commit that only modified whitespace (making indentation consistent). This made the git blame useless for all the lines it modified.
I added the hash of that commit to a
.git-blame-ignore-revsfile in our repo, and ensured everyone runsgit config blame.ignoreRevsFile .git-blame-ignore-revswhen setting up the dev environment. Now the blame skips that commit and we can more easily see why those lines were added or changed.You can use
git blame -wfor this that ignores whitespaces. For code movements you can use-C(stacks multiple times). But thx, didn’t know ignore-revsThanks! I didn’t know about
-C. I think I’ll still use the ignore revs file for bigger projects, but it’s nice to know about the commands.I feel like you probably shouldn’t care who wrote code from 10 years ago…
I generally don’t care who wrote it, I care about finding the commit it was part of so I can have the context for why it was written.
Good point.
This is a nice list. One of my favorites is enabling
interactive.singleKey.My god, I wanted this to exist so many times! Thank you!
Similarly, under ZSH, I have ~single-key bindings for
git diff:and for
git status:that I use all the time.
I use
format.signatureto replace the git version on patches produced withgit-format-patch. Makes no functional differences and you can self-express using an entire new medium!So instead of say
your patch now ends with
To preserve commit notes when recreating refs:
To never abbreviate the commit SHA in
git-log:To remove
a/andb/from diffs so that you can copy paste them like a person whose humanity is respected:I’ve ended up disabling
diff.noprefixas it definitely caused issues with being able to dogit format-patch/git applybut +1 it as being super useful!You can still
applypatches with-p0:git apply -p0 my.diffHeh – while reading this I thought that sounded like a nice thing to turn on, but had then quickly had exact same concern. However, after testing it out it looks like in recent versions of git (somewhere between 2.34 and 2.43, not sure offhand exactly when)
format-patchhas been fixed to override that setting and always include thea/bprefixes.Forgot to mention that caveat, thanks. I turn it off and on with shortcuts when I have to deal with patches.
Things I have in my
.gitconfigwhich weren’t mentioned:diff.renames = copiesmakesgit diffdetect copies betterdiff.mnemonicprefx = truethis changesa/andb/depending on what you compare. I don’t really notice it that much.diff.algorithm = patiencebetter diffsbranch.autoSetupRebase = alwaysautomatically sets the upstream of new branches to the branch you based it on.rebase.abbreviateCommands = truemakes interactive rebase commands one letter. This is probably mandatory if you rebase enough.init.defaultBranch = master;)alias.fixes = show -s '--pretty=format:%h (\"%s\")'. This prints the short hash and summary likea8dc4965f09 ("clk: clk-gpio: add actual gated clock")for use inFixes:tags or commit messages.advice.detachedHead = falsesuppresses the useless warning message about detached heads.Depending on the project, I also have
submodule.recurse = truemakes things likegit greprecurse into submodules by default. This is super handy if you have a bunch of submodules since you can easily search the whole project.diff.submodule = logshows the log of commits added in submodules. This is a lot more useful than the default IMO.Why the wink?
The OP suggested changing it to be the other way.
They are trolling, you got hooked
I suppose this counts as hooked, but I want them to say explicitly what they find funny.
What is this one for? Why would you want to see
pinstead ofpickin the command list?You can always enter your own commands as single letters - or was that not true in some early version of git?
It’s easier to edit. You just delete a single letter and replace it with whatever you want.
This isn’t an issue for modal editors :)
I use a modal editor. Saves a keypress. Also convenient with visual blocks.
Does your editor have a built-in single-key binding for “replace the current word with a single letter”? In Vim, replacing one letter with a different letter is two keystrokes (e.g.
rf) but I can’t think of a way to replace a multi-character word with one letter in fewer than four keystrokes (cwf^[).Nope, but four keystrokes really isn’t an issue compared to 2, it’s just 2 characters.
I thought it would matter much greater if you needed to backspace a few more times, but yes, you do save at least 2 characters even with modal editors.
Oh, OK. I don’t think I’ve ever found deleting a single letter any easier or harder than deleting a word - but I guess everyone uses editors in different ways. Thanks!
I always learn something new from Julia. Was just lamenting I had to type my (usefully verbose) branch names when I push them but now I don’t!
I put
ff = onlyonmergerather thanpull, this way it affects both pull and every other merge operation, making it much cleaner.Non-ff merges can still be created using
--no-ff.I prefer
upstream, this way it only pushes to the branch configured as the current’s upstream. No name matching, explicit configuration.The one major drawback is it requires religiously creating feature branches with
--no-trackto avoid tracking the base branch. Disabling tracking can be set globally, but then it’s a pain in the ass when you’re actually trying to create tracking branches for upstream’s.Other config items I have:
log.decorate true, adds refs matching the commits to the log, useful to get a quick overview of how far ahead you are, or of stacked branchesfetch.parallel 0allows running concurrent fetches, mostly useful when there are multiple remotes or submodules being fetched at the same time, otherwise fetches are sequentialreceive.autogc falseandreceive.unpackLimit 1can make fetching complete faster as git will never bother unpacking objects on fetch, and will not try to immediately run a GC