Git works immediately, but a small amount of configuration makes daily work much smoother. Good defaults reduce mistakes, remove repeated typing, and help keep your environment consistent across projects.
In this lesson, you will cover:
Tip: Start with a few settings you use every day. You do not need a giant
.gitconfigto get real value.
.gitconfig ScopesGit reads settings from three main levels:
Most personal preferences belong in global config, while project-specific exceptions belong in local config.
Useful commands:
git config --list
git config --list --show-originTypical files are:
/etc/gitconfig~/.gitconfig.git/configLocal settings override global ones, and global settings override system ones.
Git writes author information into each commit, so configure identity first.
git config --global user.name "Vishvesh Patel"
git config --global user.email "vishvesh@example.com"Verify the values:
git config --global user.name
git config --global user.emailIf one repository needs a different email, set it locally:
cd company-project
git config user.email "vishvesh@company.com"Git may open an editor for commit messages, rebases, or merge messages. Pick one you already use.
git config --global core.editor "code --wait"Or:
git config --global core.editor "vim"To make new repositories start on main:
git config --global init.defaultBranch mainNote: This affects only future
git initrepositories. Existing repositories keep their current branch names until you rename them.
.gitconfig FileA .gitconfig file is a simple INI-style file.
[user]
name = Vishvesh Patel
email = vishvesh@example.com
[core]
editor = code --wait
[init]
defaultBranch = mainYou can edit it directly or let git config write the entries for you.
Aliases turn longer commands into shorter ones.
Basic examples:
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commitThat lets you run:
git st
git co main
git brA compact history view is one of the most useful aliases you can add.
git config --global alias.lg "log --oneline --graph --decorate --all"Then run:
git lgA few more practical shortcuts:
git config --global alias.last "log -1 HEAD"
git config --global alias.unstage "restore --staged"
git config --global alias.amend "commit --amend"Aliases should make common work faster, not hide commands you do not understand.
Some files should stay out of git status in every repository, such as:
.DS_Store.vscode/Create a personal ignore file:
touch ~/.gitignore_globalExample contents:
.DS_Store
.vscode/
*.swp
.env.localTell Git to use it:
git config --global core.excludesfile ~/.gitignore_globalThis keeps machine-specific clutter out of all repositories without editing each project's .gitignore.
git config --global user.name "Vishvesh Patel"
git config --global user.email "vishvesh@example.com"
git config --global core.editor "code --wait"
git config --global init.defaultBranch main
git config --global core.excludesfile ~/.gitignore_global
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg "log --oneline --graph --decorate --all"Git configuration lives at system, global, and local levels. Set your identity, choose a comfortable editor, define main as the default branch for new repositories, add a few aliases, and use a global ignore file for OS and editor clutter. Small config improvements make Git easier every day.
<MCQExercise
exercise={{
id: 'git-aliases-config-q1',
title: 'Exercise 1: Picking the right config scope',
description: 'Which Git configuration scope should you use for a custom email address that only applies to one specific repository?',
options: [
{ id: 'a', text: 'system' },
{ id: 'b', text: 'global' },
{ id: 'c', text: 'local' },
{ id: 'd', text: 'remote' },
],
correctId: 'c',
explanation: 'Local configuration lives in .git/config inside the repository and overrides broader settings for that one project. That is the right place for repo-specific identity changes such as a different work email.',
wrongExplanations: {
a: 'System configuration affects all users on the machine and is too broad for one repository-specific email.',
b: 'Global configuration applies to your whole user account, so it would affect all repositories unless overridden.',
d: 'A remote is a repository endpoint, not a Git config scope.',
},
}}
/>
<MCQExercise
exercise={{
id: 'git-aliases-config-q2',
title: 'Exercise 2: Understanding aliases',
description: 'After running git config --global alias.st status, what does git st do?',
options: [
{ id: 'a', text: 'It opens the stash list' },
{ id: 'b', text: 'It runs git status' },
{ id: 'c', text: 'It stages all files automatically' },
{ id: 'd', text: 'It starts a new Git repository' },
],
correctId: 'b',
explanation: 'Aliases are shortcuts for longer commands. In this case, st becomes another way to run git status.',
wrongExplanations: {
a: 'That would only happen if you explicitly created a stash-related alias.',
c: 'Staging files is a different operation such as git add.',
d: 'Initializing a repository is done with git init, not git status.',
},
}}
/>
<MCQExercise
exercise={{
id: 'git-aliases-config-q3',
title: 'Exercise 3: Global ignore behavior',
description: 'Why would you use ~/.gitignore_global with core.excludesfile?',
options: [
{ id: 'a', text: 'To ignore machine-specific files like .DS_Store across all repositories' },
{ id: 'b', text: 'To delete ignored files from disk automatically' },
{ id: 'c', text: 'To replace every project's .gitignore file permanently' },
{ id: 'd', text: 'To stop Git from tracking source code in the current branch' },
],
correctId: 'a',
explanation: 'A global ignore file is useful for patterns that are personal or machine-specific, such as OS artifacts and editor files. It keeps those items out of git status without forcing every repository to duplicate the same rules.',
wrongExplanations: {
b: 'Ignore rules affect tracking and status behavior, not physical deletion of files.',
c: 'Global ignore complements project-specific .gitignore files rather than replacing them.',
d: 'It filters specific file patterns, not all source code or whole branches.',
},
}}
/>
Set the work identity per repository with git config user.email you@company.com, which writes to that repository's .git/config and overrides your global value. For more than a couple of repositories, use conditional includes: in ~/.gitconfig, an [includeIf "gitdir:~/work/"] section pointing at a second config file applies automatically to anything under that directory. That way a new clone in the right folder gets the right identity without you remembering to set it.
git config --global alias.<name> '<command>', so git config --global alias.st status gives you git st. Aliases can chain flags, as with a pretty log: alias.lg "log --oneline --graph --decorate --all". Prefixing the value with ! runs a shell command rather than a Git subcommand, which lets an alias combine several steps. Aliases live in your config, so they are yours alone and do not travel with the repository.
Start with the ones you type dozens of times a day, st for status, co for checkout or switch, br for branch, ci for commit. Then add the ones whose full form you would never type: a graph log, last for log -1 HEAD, and unstage for restore --staged. Do not alias destructive commands to short names; a two-character alias for reset --hard is an accident waiting to happen.
A .gitignore in the repository describes what that project should not track, and belongs in version control. A global ignore file, set with git config --global core.excludesfile ~/.gitignore_global, covers things specific to you: .DS_Store, editor directories such as .idea/ and .vscode/, and local scratch files. The distinction matters as courtesy: your colleagues on other systems should not have to carry ignore rules for your operating system and editor.
Four are worth setting immediately. init.defaultBranch main, so new repositories match what hosting platforms expect. pull.rebase true, which stops a plain git pull littering history with merge commits. fetch.prune true, so branches deleted upstream disappear from your local list. And core.editor set to something you can exit, which spares you meeting Vim unexpectedly. Adding rerere.enabled true pays for itself the first time you rebase through the same conflict twice.
Pin one repository inside another with Git submodules: clone with --recurse-submodules, know the two update commands, handle detached HEAD and subtrees.
Write Git commit messages that stay useful: an imperative summary, a body that records why, Conventional Commits and enforcement with commitlint and Husky.
Learn what Git is and why version control matters: distributed versus centralized systems, how Git stores history and the key terms to know first.