DevFox Labs
HomeLearningToolsAboutContact
beginner30 minby DevFox

Configuring Git the Way You Want It

The three config levels, your editor, line endings, and the handful of settings that remove daily friction — each introduced by the annoyance it fixes.

  • Git

On this page

  • What a setting actually is
  • Why Git keeps your settings in three places
  • Naming the branch a new repository starts on
  • Why Git ever opens a text editor
  • The invisible characters that fake a change
  • Five settings that remove daily friction
  • Aliases, or how to stop typing so much
  • Where your settings actually live
  • Reading a setting back, and undoing one
  • A cheat sheet to keep
  • Where to go next
DevFox Labs

Structured lessons and courses for developers who care about craft.

Platform

HomeLearningAll lessonsAboutContact

Legal

Terms of ServicePrivacy PolicyCookie Policy

© 2026 DevFox Labs. All rights reserved.

    In the last lesson you typed your name and email into Git and moved on. That was not a one-off ritual. It was your first two settings, written as two lines of plain text into a file that Git reads before every single command it runs.

    Git arrives knowing nothing about you: not your name, not which editor you can survive, not how your operating system ends a line of text. It has a default for all of it, and a few of those defaults are older than you would like. By the end of this lesson you will have a config file you can read line by line, explain to someone else, and carry to every machine you ever own.

    What a setting actually is

    When you ran git config --global user.name "Ada Lovelace", Git did not tuck your name into a database somewhere. It appended a line to a text file in your home folder. That is the whole mechanism: a setting is a key, a value, and a file.

    Keys always come in two parts joined by a dot — a section, then a name inside it. user.name is the name entry in the user section. core.editor is the editor entry in core. Once you see that shape, config keys stop looking like magic words you have to memorise from blog posts:

    bash
    git config --global <section>.<key> "<value>"

    You already know the pattern from lesson two. Everything else in this lesson is the same command with different keys.

    Nothing here can damage your work

    Configuration changes preferences, never content. No setting in this lesson touches your files or your project's history — the worst a wrong value can do is annoy you until you notice. Every one of them can be changed again or removed with --unset, which you will meet near the end.

    Why Git keeps your settings in three places

    Here is the awkward situation Git has to handle. You have one computer and many projects on it. Most of what you want is the same everywhere — your name is your name, your editor is your editor. But not everything. The repositories you touch for your employer should carry your work address, not the personal one you use for weekend projects. And if other people log into the same machine, some settings should apply to all of them.

    One file cannot express that, so Git reads three and stacks them.

    1. Local — one repository

      Lives in that repo's .git/config. Set it by running git config inside the repo, with --local or with no level flag at all. This is where a work email belongs.

    2. Global — you, on this machine

      Lives at ~/.gitconfig, reached with --global. Roughly ninety percent of your settings belong here, including the name and email from the last lesson.

    3. System — every user on the machine

      Lives at /etc/gitconfig, reached with --system. Editing it usually needs administrator rights, and in practice it holds whatever your installer put there. You will likely never write to it.

    The width is how many repositories a level covers. The narrowest one that has an opinion wins.

    Think of a shared workshop. There are rules posted at the entrance that apply to everyone who walks in, the way you personally like your own bench arranged, and a note taped to one specific job saying "this one is different". The specific note wins.

    Git works exactly that way: the most specific level wins. Local beats global, and global beats system. When a setting is not what you swear you set, ask Git where each value came from:

    bash
    git config --list --show-origin

    Every line is prefixed with the file it was read from:

    text
    file:/etc/gitconfig       init.defaultbranch=main
    file:/home/ada/.gitconfig user.name=Ada Lovelace
    file:/home/ada/.gitconfig user.email=ada@example.com
    file:.git/config          user.email=ada@bigcorp.com

    Read that last pair together. Two files set user.email, and because .git/config is the local file, the work address is the one in effect here. That is not a bug; it is the everyday reason local config exists. Inside your employer's repository, run:

    bash
    git config user.email "ada@bigcorp.com"

    No --global, so the value lands in that repository's .git/config and nowhere else. Every other project on the machine keeps your personal address, and no commit ever again carries the wrong one to the wrong place.

    Naming the branch a new repository starts on

    When Git creates a repository it has to call the first line of history something. For most of Git's life that name was hardcoded to master. In 2020 the community moved to main, GitHub and GitLab followed for new repositories, and Git 2.28 added a setting so you could pick your own instead of renaming by hand every time.

    bash
    git config --global init.defaultBranch main

    Two concrete reasons to set it. First, a repo whose first branch is master while the hosting service expects main is a small, dumb source of friction the first time you push. Second, until you decide, Git prints a paragraph of advice about it on every single git init, and advice you have read forty times is noise.

    Why Git ever opens a text editor

    Some of what Git needs from you does not fit on a command line. A commit message that deserves a paragraph of explanation. A note about why a merge happened. A list of instructions for rewriting several commits at once. Git does not have a text box of its own, so it does the sensible thing: it opens a text editor, waits for you to write and save, then reads the file back.

    If you never chose an editor, you get whatever the system considers default. On a lot of machines that is vim — a fine editor, and a genuinely alarming surprise if you have never met it and cannot work out how to get out. Choose deliberately instead:

    bash
    git config --global core.editor "code --wait"   # VS Code
    git config --global core.editor "nano"          # nano
    git config --global core.editor "vim"           # vim

    The --wait on the VS Code line is not decoration, and leaving it off produces a confusing failure. Normally code hands the file to the VS Code window you already have open and exits immediately. Git sees the editor finish about a tenth of a second after launching it, reads a file you have not typed in yet, finds it empty, and aborts with "Aborting commit due to empty commit message" — while your commit message sits there half-written on screen. --wait keeps code running in the foreground until you close the tab, and closing the tab is the signal Git is waiting for.

    If you land in vim by accident

    Type :cq and press Enter to quit with an error, which cleanly cancels whatever Git was about to do — no commit, no harm. To finish normally instead, press i to start typing, then Esc, then :wq and Enter to save and exit.

    The invisible characters that fake a change

    Picture this. A colleague on a different operating system opens a file you wrote, changes one word, and saves. Now git diff reports that every single line in the file changed. Four hundred lines, none of them different to a human eye. Reviewing that is impossible, and merging two branches that both did it produces conflicts about nothing at all.

    The cause is two characters you cannot see. Windows ends a line of text with a carriage return followed by a line feed; macOS and Linux use a line feed alone. Many editors rewrite the whole file to their own convention on save. Git stores exactly the bytes it is handed, so to Git every line really is different.

    The fix is to agree that history stores line feeds, and let each machine do what it likes on disk. Which value you want depends only on what your own editors expect.

    Windows

    core.autocrlf true

    Strips carriage returns on the way into a commit and puts them back when files land on disk — which is what a Windows editor expects to find.

    macOS and Linux

    core.autocrlf input

    Strips them on the way in and leaves your files alone on the way out, which is right on systems that never wanted carriage returns in the first place.

    Both store line feeds in history. They differ in what lands in your working folder.
    bash
    git config --global core.autocrlf true    # Windows
    git config --global core.autocrlf input   # macOS and Linux

    Teams eventually pin this per project in a .gitattributes file so it does not depend on everyone configuring their laptop correctly, but your global setting is what protects you today.

    Five settings that remove daily friction

    None of these are required, and Git works without them. Each one removes a specific small irritation you would otherwise meet weekly.

    bash
    git config --global pull.rebase true
    git config --global push.default simple
    git config --global color.ui auto
    git config --global core.pager "less -FR"
    git config --global help.autocorrect prompt

    When you pull a branch that moved on while you were working, Git has to decide what to do with your local commits, and by default it stops to ask. pull.rebase true answers the question once and for all: replay your commits on top of what arrived, so history stays a straight line instead of collecting merge commits that say nothing.

    push.default simple makes a bare git push mean "send the branch I am on to the branch of the same name upstream" — the reading you almost certainly intended, and the one least likely to push something you forgot about.

    color.ui auto colourises output in your terminal so added and removed lines are instantly distinguishable, while staying plain text when you pipe output into another program that would only be confused by colour codes.

    core.pager "less -FR" fixes two nuisances at once: -F skips the pager entirely when the output already fits on one screen, so a three-line log stops taking over your terminal and demanding q, and -R lets those colours through instead of showing you the raw codes.

    help.autocorrect prompt catches git stauts and asks whether you meant status, rather than refusing and making you retype. Set it to a number like 20 instead and Git waits two seconds and runs the corrected command itself, which is fine until the day it guesses something you did not want.

    Aliases, or how to stop typing so much

    You are going to type git status thousands of times. Not figuratively — a working day involves dozens of them, and that adds up over a career. An alias is a nickname for a longer command, stored in your config like any other setting:

    bash
    git config --global alias.st "status -sb"
    git config --global alias.lg "log --oneline --graph --decorate"
    git config --global alias.unstage "restore --staged --"

    You call them by name: git st, git lg, or git unstage notes.txt. Git expands the alias and runs the real command underneath, and anything extra you type passes straight through to it — which is why git unstage notes.txt works even though the alias never mentions a filename.

    Keep the list short and readable. An alias you cannot decode six months from now is worse than the command it replaced, and an alias you rely on is a small trap on any machine that is not yours.

    An alias cannot rename a real command

    If you define alias.status, Git ignores it and runs its own status. Built-in commands always win, which means no alias can quietly turn a familiar command into something else — reassuring when you sit down at a colleague's machine.

    Where your settings actually live

    Every --global command in this lesson has been editing one plain text file: ~/.gitconfig in your home folder. On Windows that is C:\Users\YourName\.gitconfig, which Git Bash still lets you write as ~/.gitconfig. Nothing is hidden from you — open it whenever you like:

    bash
    git config --global --edit

    That opens the file in the editor you just configured. After following this lesson it looks roughly like this:

    ini
    [user]
    	name = Ada Lovelace
    	email = ada@example.com
    [init]
    	defaultBranch = main
    [core]
    	editor = code --wait
    	autocrlf = input
    	pager = less -FR
    [pull]
    	rebase = true
    [push]
    	default = simple
    [color]
    	ui = auto
    [help]
    	autocorrect = prompt
    [alias]
    	st = status -sb
    	lg = log --oneline --graph --decorate
    	unstage = restore --staged --

    Look at the shape of it and the dotted keys finally make sense. The [user] header is the section, name is the key inside it, and together they are the user.name you have been typing all along. Editing this file by hand does exactly the same thing as running git config — the command only saves you from typos in the punctuation.

    Reading a setting back, and undoing one

    Two more commands and you can manage this file with confidence. To ask what a single setting is right now:

    bash
    git config --get user.email

    --get respects the same precedence as everything else, so it answers with the value actually in effect — run it inside that work repository and you get the work address, not the global one. That makes it the fastest way to check yourself before a first commit in an unfamiliar folder.

    To remove a setting you regret, name the level and the key:

    bash
    git config --global --unset alias.lg

    Removing is better than blanking. Setting a key to an empty string leaves it in the file, still overriding whatever the system config said; --unset deletes the line so the level below shows through again. If a key somehow appears twice in one file, --unset refuses to guess which you meant and --unset-all removes every copy.

    Carry this file between machines

    Once your ~/.gitconfig is how you like it, put it in a small "dotfiles" repository alongside your shell and editor settings. Setting up a new laptop then collapses to cloning that repo and linking one file, and every machine you touch behaves the same way — which matters most on the machines you use least.

    Never put credentials in a tracked config

    Git will happily store a token, a password, or a remote URL with a password baked into it, and a repository's .git/config is safe because it is never committed. A config file you commit is not. Once a secret is pushed it may already be cloned, mirrored, or scraped, so deleting it later does not undo the leak — treat it as compromised and rotate it immediately.

    A cheat sheet to keep

    Every command from this lesson, in one place:

    bash
    git config --global <key> "<value>"           # set for all your repos
    git config <key> "<value>"                    # set for this repo only
    git config --list --show-origin               # every value + its file
    git config --global --list                    # only your own settings
    git config --get user.email                   # the value in effect now
    git config --global --unset alias.lg          # delete one setting
    git config --global --unset-all <key>         # delete every copy
    git config --global --edit                    # open ~/.gitconfig
    git config --global init.defaultBranch main   # name the first branch
    git config --global core.editor "code --wait" # editor Git opens
    git config --global core.autocrlf true        # line endings: Windows
    git config --global core.autocrlf input       # line endings: mac/Linux
    git config --global pull.rebase true          # rebase instead of merge
    git config --global push.default simple       # push this branch only
    git config --global color.ui auto             # colourised output
    git config --global core.pager "less -FR"     # sane pager behaviour
    git config --global help.autocorrect prompt   # offer typo fixes
    git config --global alias.st "status -sb"     # makes `git st` work

    Where to go next

    Git now behaves like a tool that was set up for you rather than for nobody in particular. Your commits carry the right identity, new repositories start on main, an editor you can actually use opens when Git needs prose, line endings stay sane across operating systems, and a handful of small settings have quietly stopped getting in your way.

    Next comes the part you have been setting up for: your first repository and commit. You will turn an ordinary folder into a repo, choose what goes into a snapshot, and save it — and several settings from this lesson will show up in the result without you thinking about them again.

    Before you move on, spend two minutes proving the setup to yourself. Run git config --list --show-origin and read it line by line until you can name what each setting does and which file it came from. Then change one — swap the editor, add an alias, remove it again — and watch the file follow you. Config you understand is config you can fix at midnight.