jelder 3 hours ago

My favorite alias is `git out`, which just lists all unpushed commits. I use it all the time.

  [alias]
    out = "log @{u}.."
In my head I always hear it in the voice of The Terminator: https://youtu.be/8cdC1Y5oRFg?t=54
  • schacon 2 hours ago

    I should do another article on the best aliases, because this is a great one. I want it just because I want to do the Arnold voice every time.

    Now I want to do: `git to-da-choppa`

    • theshrike79 2 hours ago

      That could be just

        git add . && git commit -a -m "git to da choppa" && git push --force
      
      For when you need to Get to da choppa and don't have time to clean up =)
_kb 6 hours ago

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.

[1]: https://dandavison.github.io/delta/

  • leonheld 5 hours ago

    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.

    • JadedBlueEyes 5 hours ago

      IIRC if you pipe the output to, e.g, xclip, or redirect to a file it will give the original diff format. Not as convenient, but still workable.

      • leonheld 4 hours ago

        I... did not know that! Yep yep that should do the trick for me. Thanks a lot, actually!

        • mplanchard 4 hours ago

          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.

          • knome 3 hours ago

            rather they should detect that output is a terminal and enable the coloring

      • pca006132 4 hours ago

        Wow I never knew this, I always just type `--no-ext-diff` when piping the output. Thanks!

        • ramses0 4 hours ago

          `... | cat` is sometimes really handy (and universal)

          • lucasoshiro 3 hours ago

            I use git -c core.pager = less, but piping seems to be a less verbose option... hmmm I'll try it

      • rusk 3 hours ago

        Pipe through cat should work

    • PhilippGille 5 hours ago

      Isn't copying without the formatting just a `<your diff command> | pbcopy` away?

      • genewitch 2 hours ago

        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.

        • chuckadams an hour ago

          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.

  • schacon 6 hours ago

    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.

chungy 6 hours ago

My own ~/.gitconfig looks like this:

    [alias]
     co = checkout
     ci = commit
     st = status
     br = branch
     hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
     type = cat-file -t
     dump = cat-file -p
     dft = difftool
    [tag]
     sort = version:refname
    [tar "tar.xz"]
     command = xz -c
    [tar "tar.zst"]
     command = zstd -T0 -c
    [log]
     date = iso-local
    [pull]
     ff = only
    [diff]
     tool = difftastic
    [safe]
     directory = *
    [advice]
     detachedHead = false
    [init]
     defaultBranch = master
  • chungy 6 hours ago

    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.

    • schacon 6 hours ago

      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.

      • feelamee 3 hours ago

        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.

        • desperatecuban 2 hours ago

          Dont the many git TUI clients (tig, lazygit, ...) work like that with keybindings?

JulianWasTaken 4 hours ago

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.

[1]: https://github.com/Julian/dotfiles/blob/main/.config/git/con...

tome 5 hours ago

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 wrote up more here: https://stackoverflow.com/a/63739655/997606

I also wrote up how to use diff3 style to make resolving rebase (or merge) conflicts a mechanical procedure: https://h2.jaguarpaw.co.uk/posts/git-rebase-conflicts/

conaclos 7 hours ago

Some extra options I like:

  [apply]
    # Remove trailing whitespaces
    whitespace = fix
  [color "diff"]
    whitespace = red reverse
  [diff]
    colorMovedWS = allow-indentation-change
  [format]
    pretty = fuller
  [log]
    date = iso
  [pull]
    ff = only
  • schacon 7 hours ago

    I did almost put `log.date iso` in there, I like that one too.

  • opello 3 hours ago

    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.

cassepipe 3 hours ago

I discovered that you can have git use the pager you like so I set it to my darling : bat

    git config --global core.pager bat
https://github.com/sharkdp/bat/
  • oneeyedpigeon 2 hours ago

    Is there an advantage to doing this over setting the GIT_PAGER environment variable?

    (Weirdly, git doesn't seem to honour the PAGER var (which would be even better), although its man page claims it does)

    • lucasoshiro 2 hours ago

      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

  • betimsl 3 hours ago

    It just makes everything perfect.

neals 7 hours ago

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...

  • lucasoshiro 2 hours ago

    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.

    For instance, I wrote this post last year about how you can use Git as a powerful debugging tool: https://news.ycombinator.com/item?id=39877637

  • juancroldan 4 hours ago

    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).

  • jbverschoor 7 hours ago

    Nothing wrong with a gui. Esp with git imo. The process doesn’t require blazing fast agility, but careful review and selection.

    Graphical diff viewers are way better anyway.

  • pfg_ 5 hours ago

    Setting merge conflictstyle diff3 or zdiff3 will improve your experience if you ever do any merging

    • vlovich123 2 hours ago

      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.

  • jeffwass 7 hours ago

    Of course, there's an xkcd for that : https://xkcd.com/1597/

    • eastbound 6 hours ago

      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.

      • tex0 3 hours ago

        Maybe git is just too complicated for average users (myself included).

        • ajross an hour ago

          > 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.

musikele 3 hours ago

I also have this alias to my config

    [alias]
       lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --branches
It shows a coincise colored graph of your commits and branches.
  • alex_smart 3 hours ago

    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.

rowanseymour 2 hours ago

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.

trebligdivad 2 hours ago

I took most of the 'Clearly better' and a few others; but NOT the prune options. I don't like things getting deleted without me saying yes!

rmccue 3 hours ago

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.

idoubtit 7 hours ago

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 = ./`.

silvanocerza 2 hours ago

Happy to notice I already use most of these. The only ones I didn't know are diff.mnemonicPrefix, diff.renames and commit.verbose.

My config if you'd like to steal it, also here: https://github.com/silvanocerza/dotfiles/blob/master/git/git...

Mind that you need diff-so-fancy for this work correctly. https://github.com/so-fancy/diff-so-fancy

    [alias]
        co = checkout
        ci = commit
        cl = clone
        st = status
        f = fetch
        br = branch
        lg = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) %C(bold green)(%ar)%C(reset) %C(yellow)- %an%C(reset)%C(auto)%d%C(reset)%n"        "%C(white)%s%C(reset)' --all
        lgg = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'
        type = cat-file -t
        dump = cat-file -p
        # Lists all local branches that have been deleted on remote
        gone = ! "git for-each-ref --format '%(refname:short) %(upstream:track)' | awk '$2 == \"[gone]\" {print $1}' | xargs git branch -D"
    
    [color]
        ui = true
    
    [push]
        default = simple
    
    [merge]
        tool = meld
        conflictStyle = zdiff3
    
    [diff]
        algorithm = histogram
        colorMoved = dimmed-zebra
        colorMovedWS = no
        mnemonicPrefix = true
        renames = true
    
    [rerere]
        enabled = true
    
    [pager]
        branch = false
    
    [core]
        pager = diff-so-fancy | less --tabs=4 -RFX
        fsmonitor = true
        untrackedCache = true
    
    [color "diff-highlight"]
        oldNormal = red bold
        oldHighlight = red bold 52
        newNormal = bold
        newHighlight = green bold 22
    
    [color "diff"]
        meta = yellow
        frag = magenta bold
        commit = yellow bold
        old = red bold
        new = green bold
        whitespace = red reverse
    
    [diff-so-fancy]
        markEmptyLines = false
    
    [filter "lfs"]
        clean = git-lfs clean -- %f
        smudge = git-lfs smudge -- %f
        process = git-lfs filter-process
        required = true
    
    [pull]
        rebase = false
    
    [init]
        defaultBranch = main
    
    [column]
        ui = auto
    
    [branch]
        sort = -committerdate
    
    [commit]
        verbose = true
tobyhinloopen 7 hours ago

I immediately applied most of these, thanks!

leslielurker 6 hours ago

Wow I had no idea these were available. I really hope some of these become the default config.

recroad 3 hours ago

I’ve been practicing trunk-based development for the last year and none of these Git tips apply.

  • schacon 3 hours ago

    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.

    [0] https://scottchacon.com/2011/08/31/github-flow/

ajross 2 hours ago

> 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.

lylejantzi3rd 4 hours ago

# clearly makes git better

If these options clearly make git better, why aren't they the defaults?

  • Forge36 4 hours ago

    The default rarely change avoid breaking changes.

    • tux1968 3 hours ago

      It would be nice to have modern defaults protected behind a single option.

      defaults = 2025.01

      Or whatever.

high_byte 4 hours ago

this is amazing. I've been swearing at diffs which I now know are myers algorithm and histogram diffs are exactly what I've been wanting!!

carlosneves 7 hours ago

Greatly appreciate these tips! I'll apply most of them, especially the diff ones.

Dlooooloo 4 hours ago

I like main as a branch default.

It's shorter, sounds nicer.

nialv7 6 hours ago

when's git-fsmonitor going to support linux?

FirmwareBurner 7 hours ago

What about the famous "disable garbage collection"?

dark-star 7 hours ago

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

  • schacon 7 hours ago

    I mentioned it in the post as well, but Git will look in `.config/git/ignore` if you prefer to just use that rather than setting a new path.

    There's also a possible downside here in having things hidden for you but not for others since it's not in your `.gitignore` project file.

    I'm honestly kind of on the fence about this one, I don't have much in that file for those reasons.

    • fragmede 7 hours ago

      I have .DS_store in mine, as I'm on a Mac and don't need to spread that to others.

      • zelphirkalt 6 hours ago

        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.

        • tomnipotent 6 hours ago

          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).

          • zelphirkalt an hour ago

            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?

          • mvanbaak 5 hours ago

            if one would use ".editorconfig" it works with multiple editors/IDEs. See editorconfig.org for more info :)

  • whirlwin 7 hours ago

    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.

  • wh33zle 6 hours ago

    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.

aboardRat4 5 hours ago

[flagged]

  • ahartmetz 5 hours ago

    But "main" is a much better name anyway (maybe my non-native English bias), so I don't mind in this particular case.

    • gnuly 4 hours ago

      [dead]

  • becquerel 5 hours ago

    There is truly no suggestions of change to people's lives small enough that someone won't make opposing it part of their identity.

    • zppln 5 hours ago

      The same could be said for proposing it...

  • leonheld 4 hours ago

    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?

    And PS: I'm not from the USA ;-)

thro949494i 7 hours ago

> Default branch

> Personally, I don’t have a problem with master

> 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!!!

  • randunel 7 hours ago

    While your comment is in jest, I agree with the sentiment. The whole "main" debacle sucks and, to this day, still breaks everyone's git usage.

    • superb_dev 7 hours ago

      Honest question: What has it broken about your git usage? I haven’t really noticed a problem.

      Sometimes a repo uses “main” and sometimes “master”. It’s not like “master” was the only option before

      • homebrewer 3 hours ago

        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.

      • trebligdivad 2 hours ago

        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.)

      • blueflow 5 hours ago

        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'.

      • randunel 7 hours ago

        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.

    • thro949494i2 6 hours ago

      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.

sliq 7 hours ago

Why is git even in development? It's exactly the same like 15 years ago, right? ... right?

  • Cthulhu_ 4 hours ago

    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).

Galanwe 2 hours ago

I use `defaultBranch = master`, because the prude trend of forbidding words based on obvious miscontextualization is more harmful than helpful.