While everyone is here considering their life choices (at least as far as they relate to ~/.gitconfig), highly recommend delta [1] as a companion to the git cli.
After using delta for a while, I'm going back to the regular diff view... it's not that it isn't good, but I'm constantly copying diffs (yes, I know I can generate patches) and the pretty output breaks that workflow.
Also, when your terminal is a bit small it's a bit hard to see things. But it's really good software, I recommend anyone who's reading to give it a try.
Most tools that do formatted output, if they’re well-behaved, should try to detect if their output is a pipe and if so, disable formatting.
Some examples that I can think of off the top of my head (in addition to git) are ripgrep and jq, both of which do the right thing and strip formatting.
I have Gemini set to decipher HN comments that I don't immediately understand. This is a macos only command `pbcopy`?
Aside: Gemini mentioned it didn't want me to ask it questions about bikeshedding what shade of blue on a website header so I think it's got our number.
Yes pbcopy is a mac thing. On Linux, there are of course many different commands in different environments/distros. xsel, xclip, wl-clipboard, wlclip to name a few.
On windows, powershell has Get-Clipboard and Set-Clipboard, and cmd.exe has `wsl` to fix the issue of having used cmd.exe to begin with.
I really wanted to add this (I linked it in the last paragraph) but I really wanted to keep the recommendations globally applicable in vanilla git. Delta is awesome though.
Shortened aliases come from cvs/svn land, sorting tags by a logical manner, adding some extra archive types for "git archive", making it so git log always shows my local time zone, pull will never do a non-ff merge, make it so Git doesn't complain about repositories in places it doesn't like, turning off an annoying message about a detached HEAD state, and shut git up about the default branch.
Yeah, I didn't do aliases on purpose, because I wanted everything to be fairly global, where I feel like aliases are more personal. But yes, aliases are great.
as for me, I want something more.
Like git shell. Where I no need to write git, git, git again and again.
Strange that there is no something like this yet.
yes, but I prefer writing status, stash, checkout, commit hand by)
So, the more I think about my previous comment the less sense I see in such feature :)
Do your aliases even save you any keystrokes? Most shells support auto complete, and you still have to type "git" unless you have a shell alias for it.
I guess what I'm git-ing at is a truly efficient alias would be embedded in the shell. For a while I had "gsno = git status --uno" although it's been so long since I used it, I forget what the options even did. Somehow I get by with only stock commands.
Another helpful alias I used to use was ctrl-space, I had aliased for 'make'. Somehow I liked it because you can almost gesture it with slamming both hands down simultaneously.
I agree with the recommendation to use (z)diff3. I think the article massively understates the case! Three way diff makes it possible to resolve some conflicts that are literally impossible to resolve without it. Why impossible? Because with default style adding conflicting things at the same place is indistinguishable from removing the same things at the same place. You need to be able to see the base to determine that.
I also use that color.diff.whitespace "red reverse" and along with it diff.wsErrorHighlight all. I recall needing to set both in the past but in trying to find out why that might have been superseded by only needing the latter. I'm not quite sure.
Mine is here [1], I basically had all of these set already (other than column ui which I don't like), but I suspect that's just because I've probably previously read nice posts by Scott and others talking about them.
Maybe trading alias tips is another useful thing to do though, hence sharing the link.
I never used that env variable, but, an advantage is that you can put all your git configs in one file and reuse it across different machines, just like any dotfile.
If you use --local instead of --global, you can configure just for the current repository, useful if may find that delta is or isn't the best choice just for that repository
How much of this is for a noob like me that just uses vscode? I hardly ever see the git command line, and when I do see it, its trouble beyond what anybody can fix...
VSCode git interface is actually pretty powerful, 99.9% of the git actions I do are already covered there, including merging, stashing, tagging, getting output from the git hooks...
However changing the diff algorithm is still a nice one, both for solving conflicts and to avoid the ocassional bad automated merges (the latter is scarier as you don't even know you pushed something wrong).
I wouldn't like to be this kind of person, but, in the case of git, the best you can do you is forcing yourself little by little to use the Git CLI. It's far from being beginner friendly, but it shows the things the way the really are. GUI git tools hide things under their hood, which is ok for most cases but when you need a little more complex thing you are limited to their capabilities.
I just use kdiff3 - automatically solves most merge conflicts & it’s rarely to never done so incorrectly. And when it can’t resolve the merge conflicts, line alignment is very nice. I prefer it to the cluttered experience of BeyondCompare and other more “feature-filled” options.
Should create an XKCD with “There is always n+1 Git client GUI”.
EVERY new employee arrives saying “Hey I’ve found this great UI for git, this one really nails it and makes git easy” and every time it’s a new Git UI that I’ve never heard of. It’s the “hello world” of startups: Creat their great git UI and publish it.
Then they commit with the default crappy commit messages and they don’t know how to git-rebase-i.
> Maybe git is just too complicated for average users (myself included).
Then use the vscode wrapper, or whatever you choose.
People complain that "git" is complicated when what is really happening is that they're looking at a revision management problem like a merge conflict or regression bisection, or having to split/refactor a giant blob of changes as demanded by an upstream project, etc...
Those tasks are complicated, necessarily. And git is a tool for doing them. But people tend to get confused about this and blame the tool and not the problem. But a better UI isn't going to make that split not suck.
On github you can add the ssh key for authentication but also for signing. Unfortunately you have to add the key twice but once you've done it, you get rid of the `unverified` label within a commit.
I really wish they'd update the default config once there's consensus that something new is optimal. I'm wary of even adding the config settings in this article in case things change in the future and I continue oblivious with a now dated setup.
I strongly disagree. Publishing a new branch on the remote should be an explicit operation. And git push will already tell you the command you need to run so it isn't an issue with having to remember another random command.
That was a useful read. I'd been frustrated by `merge.conflictstyle = diff3` so I'm glad I learned about `zdiff3`.
I also discovered `fetch.prune` and `pull.autoSetupRemote` which will slightly enhance my workflow.
My only disagreement is with the diff prefixes. I prefer to display one path starting with ".", so that I can double-click it and paste it. So I don't want contextual prefixes, I'll keep my `diff.dstPrefix = ./`.
Forces pushes are dangerous enough as it is, so I'm mystified on why git doesn't insist you know the state of upstream before running it.
Sadly you can't make it the default, so I resort to:
[alias]
force-push = push --force-with-lease
As for the article, I must the the weird one because I prefer most of the settings are they are or don't care. Even some of those designated as "clearly better" don't look to me.
It's unfortunat that --force-with-lease was given such a long name compared to the strictly more dangerous --force. And yes, it would be great if we could configure --force to behave like --force-with-lease - it's not like original --force behavior is ever desirable for human operators.
I have something almost identical, except for the `—-graph` part. That way I have the flexibility to get either the linear view or the graph view by adding that single flag.
Nit for schacon: in the "Listing branches" section, you say branch.sort + column.ui and talk about these as first/second options, but the commands are in the opposite order so it reads a little confusingly.
Wow this is neat. I never really bothered to deep-dive into my git configuration, but some of these are really cool.
The diff changes are awesome, and I always wondered why there isn't a global .gitignore file in the first place, seeing that every .gitignore file basically has (mostly) the same content
Or ".vscode" folder. No need to spread that to everyone, who might not even be using VSCode or VSCodium. Like we also don't see all of the following being added everywhere: ".settings" (eclipse), ".idea" (IntelliJ Idea), ".nbproject" (I believe Netbeans) and others everywhere in the repos. Yet we see it for VSCode. I think Github encourages this annoying behavior, because it is Microsoft's own tool, so it gets treated differently. People see this and copy this bad habit without reflecting on it. What so many others do cannot possibly be wrong...
I find it annoying to have those folders on my machine, that I don't need, but yet are checked into the git tree, so I basically cannot delete them, without affecting another person, when they pull my changes. Why you check that in bro??? Ugh.
I don't check in my Emacs backup files and shit either. I would like to aee their long faces, when faced with all of the files and folders other tools leave behind. People just aren't capable to configure their editors properly I guess and therefore rely on local config for things that could be global config or in a ".editorconfig", like for example trimming trailing whitespace.
It's very common for shared project-specific setting files to be stored in ".vscode" that are used by all developers on the project, including launch/task configurations. VSCode settings are hierarchical and composable (non-scalar keys are merged).
I am aware of that. Yet I don't see other cohorts doing that with their editor/IDE of choice. It seems to be mostly the "I don't want to configure my tools" subset, who does that. What if I switch my tool of choice 2-3 times? Do I get to commit all my project management IDE/editor specific files too? How much stuff do we want to accumulate in the git repo?
> Do I get to commit all my project management IDE/editor specific files too
Yes, if those files apply to all team members using the same tool absolutely check them in. What's the problem? It reads to me like maybe you don't know what these files are actually used for and why a team benefits from sharing them.
The whole point is, that not everyone is in the bubble of VS Code users, and not everyone wants to have that stuff on their machine, and not everyone is benefiting from it either. Imagine cloning some repo and having extra stuff in there from 3 different IDEs and 3 different editors. This stuff clutters up the repo.
There's also an ongoing effort among creators to not pollute the home directory with too many hidden files. Instead, as the blog post mentions, there exist .config/git/ignore which I think is a more scalable approach in the long run. Especially looking at the number of tools and utilities requiring one or several config files.
One of the coolest things I've learned about recently is `.git/info/exclude`. It allows you to ignore files in the local repo without modifying the repo's .gitignore
Very useful if you want to add your own .envrc or shell.nix to a repo.
I just add .envrc and shell.nix to my global gitignore. Along with docker-compose.override.yml. You can always force-add an ignored file, it'll be tracked from then on.
I'm curious what you mean. I've been practicing trunk based development since 2011[0] and all of these config settings help that flow. Arguably you don't want the rebase thing, but otherwise I can't imagine what you think here would not apply.
> Personally, I think the default behavior of Git should be to make your remote references as close to what is on the remote as possible. Prune stuff that’s gone, etc.
Yikes, no. Remote junk disappears all the time, and you never know when you'll have to recover something. Old versions of GitHub pull requests, in particular, tend to be garbage collected at the backend rapidly. It's a semi-regular occurrence for me that I have to dig through reflog to get to early work that everything else has forgotten about.
Just in general, don't delete stuff you don't know you don't need. That's just data robustness 101. nothing to do with git. Deletions should be as manual as possible, and generally done following a backup.
Nobody is stopping you from using master, you can do whatever you want. The author even recognizes that very clearly in the text.
You can name all your default branches `megazord`. Hell, you can fork git, call it "gitzord" and enforce your `megazord` branch as The Correct Main Branch Name for every user. Feels good to be free, doesn't it?
> updating the default value. I wish Git had some taste here, but they don't
So author has no preference, but git does not have a good taste here, for not breaking backward compatibility. Typical passive agresive bullshit!
I think "main" is not inclusive enough, we should use something like "non-specific-but-strong-branch". Or something that includes even stronger message. And change it every year (or month). It could be automated using github actions on all existing repos!
Also please rename "git" command, it is very insensitive word!!!
I personally haven't had a lot of breakage because my scripts never hardcoded the name of the master branch — it's possible to determine it on the fly or avoid using it. So for me it's simply the wall of useless text that wasn't there before ("using master as the name for the initial branch...") in every CI job and on every fresh system.
It's not really a major issue, but the way this "problem" was created and then forced onto the rest of us by someone with very strong opinions — but zero actual technical accomplishments in git development — is annoying, that's all. And it keeps reminding you of itself — see the first paragraph.
I'm maintaining a non-public mirror of some thousand OSS repositories. When you git clone, you do not use any "default branch", you clone the HEAD of the remote repository. This is a so-called "symbolic ref". People call it "default branch" because they don't know it can also point to a tag, a commit or be in the middle of an broken rebase. And you cannot set that information remotely via git. 'git push' can't do it, as it doesn't make sense for a bare repository.
So, if you have a git mirror in a private location that you need to push to, you get royally fucked in the arse by every project deciding to change their value for HEAD. These people basically broke 'git push' for my usecase.
So either they fix 'git push' to update the symrefs as well or shut up about using anything else than 'master'.
Even if master was the default still, nothing changes about your problem. Repositories have always been free to choose whatever name they want and change it at any time.
Is the expected behavior when a remote changes its HEAD seriously just to break when you try to push?
I do find myself forgetting which project is main and which is master so get confused a bit.
(Personally I find the use of 'master' in git fine - there has never been a 'slave' it was referring to; and 'master' is used in loads of other contexts in English; I've got a Masters degree, we have Post-masters, schools have masters and headmasters. I understand renaming it in master/slave systems though.)
> Honest question: What has it broken about your git usage? I haven’t really noticed a problem.
I assume many people, like me, would have git aliases which use a hardcoded master branch name. I several of these aliases. I've had to update them all to check what the actual master/main name is and use that instead, because our org started following the "main" naming convention and we ended up with various repos with "master" and others with "main".
I personally like standardisation, because I prefer to spend time thinking about more important things. So I was mildly (but only mildly) peeved when I had to start thinking about which repo I was on and what the "master" branch was called.
But I've updated all my aliases now, so not so much of an issue.
Previous shortcuts (dotfiles) which performed merges and other operations no longer work, as you never know if the project uses one branch name or the other.
And there's a whole new breed of programmers out there who feel offended on behalf of others about renaming versus not renaming, for example, the word "robot" comes from slave in Slavic languages and it should be banned, etc.
I somewhat agree with either banning all potentially offensive words or none at all, so let's go with none? Otherwise git is now simply gatekeeping offensiveness, and that's absurd.
They didn't ban anything? They changed the default branch name for new repositories. You've always been able to have different default branch names (I've used `trunk` for years) so if your shortcuts assumed `master` they'd have broken in a repo with a different default anyway.
I do not care about github, they can rename their domain to "smarthub.com", and force all users to migrate!
I do care if someone tries to push this stuff onto me. Changes in Git defaults would break 20 years of compatibility! It is bloody important in Linux development!
And I find it very moronic, that someone who writes "git" on every second line, complains "master" was not renamed.
You've no idea how much real social change has been brought about, when Git changed its default branch from master to main. Pardon me, I'm tearing up right now.
Most of the items in this list were introduced more recently (a lot from '22) and are definite quality of life improvements. But sure, the core of Git remains mostly unchanged - the 'porcelain', if you will - although the one major change is that they're changing the default hashing algorithm (I'm not sure if this has been done yet, I know it was decided upon in 2018).
reply