Git & GitHub Module 1 – Getting started with Git
Install Git and set up your identity
Install Git on Windows, macOS or Linux, set your name, email and first branch at the right level, and find which settings file each value comes from.
What you will learn
- Install a current Git on Windows, macOS or Linux and check its version
- Set user.name, user.email and init.defaultBranch at the right configuration level
- Find where each setting comes from with git config list --show-origin --show-scope
- Use includeIf to switch identity between personal and college or work repositories
- Add a few safe aliases and choose an editor for commit messages
Before you start
What you’ll learn · Before you start
What you will learn
- Install a current Git on Windows, macOS or Linux and check its version
- Set user.name, user.email and init.defaultBranch at the right configuration level
- Find where each setting comes from with git config list --show-origin --show-scope
- Use includeIf to switch identity between personal and college or work repositories
- Add a few safe aliases and choose an editor for commit messages
Before you start
On this page
You install Git once, and then you tell it who you are. Git writes a name and an email address into every commit you
make, so before the first commit you set both, together with the name of the first branch of every new repository:
git config set --global user.name "Your Name", git config set --global user.email you@example.com and
git config set --global init.defaultBranch main. This lesson installs a current Git on Windows, macOS or Linux, checks
which version you have, makes those three settings at the right level and shows how to see which file any setting came
from. It also sets up a different email for college or work repositories without having to remember, and a few safe
extras: a short alias, the editor for commit messages, and built-in help.
Install Git
The Git project’s download pages point to the usual way of getting Git on each system. Any recent version is fine for this track: the newest release is Git 2.56.0, and the examples here run on Git 2.54.0.
Windows
Install Git for Windows, either with the installer linked from git-scm.com or with
winget install --id Git.Git -e --source winget in PowerShell. It comes with Git Bash, a terminal that works the
way Git does on macOS and Linux, and the commands in this track work there unchanged. The installer asks a few questions
that matter later:
- The default editor, used when Git needs you to write a commit message. It suggests Vim; if you have never used Vim, pick Notepad, Notepad++ or Visual Studio Code from the list instead.
- The name of the initial branch in new repositories: choose to override it and keep
main. - Line endings: keep the suggested choice for now. A later lesson of this track explains why a
.gitattributesfile in each repository is the better place to settle them.
macOS
Apple ships Git with the Xcode Command Line Tools: run xcode-select --install in Terminal to get them. Like every
build that does not come from the Git project itself, Apple’s can lag behind the newest release, and its version line
says whose build it is: the Mac that runs this track’s examples prints git version 2.54.0 (Apple Git-157), two
releases behind. For a newer Git, use a package manager such as Homebrew, brew install git, or MacPorts,
sudo port install git.
Linux
Use your distribution’s package manager: sudo apt-get install git on Debian and Ubuntu, sudo dnf install git on
Fedora, sudo pacman -S git on Arch. Distributions package the newest Git at their own pace, and some, such as Red Hat
Enterprise Linux, ship older versions; on Ubuntu, the Git project’s page names a package archive, ppa:git-core/ppa,
with the latest stable release.
Check the version, then name your first branch
Open a new terminal after installing and run git --version. Then make a repository before changing any setting, to see
what a new installation does:
from gitsession import session
session(r"""
git --version
# A new installation: no settings of your own yet
git init first-try
cd first-try
git branch --show-current
cd ..
# Name the first branch of every new repository main
git config set --global init.defaultBranch main
git init second-try
cd second-try
git branch --show-current
git config get --show-scope --show-origin init.defaultBranch
""") Output
$ git --version git version 2.54.0 (Apple Git-157) # A new installation: no settings of your own yet $ git init first-try hint: Using 'master' as the name for the initial branch. This default branch name hint: will change to "main" in Git 3.0. To configure the initial branch name hint: to use in all of your new repositories, which will suppress this warning, hint: call: hint: hint: git config --global init.defaultBranch <name> hint: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and hint: 'development'. The just-created branch can be renamed via this command: hint: hint: git branch -m <name> hint: hint: Disable this message with "git config set advice.defaultBranchName false" Initialized empty Git repository in ~/first-try/.git/ $ cd first-try $ git branch --show-current master $ cd .. # Name the first branch of every new repository main $ git config set --global init.defaultBranch main $ git init second-try Initialized empty Git repository in ~/second-try/.git/ $ cd second-try $ git branch --show-current main $ git config get --show-scope --show-origin init.defaultBranch global file:~/.gitconfig main
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 fresh_start.py
With no settings at all, Git still gives the first branch its old default name and prints a long hint about it; the Git
project plans to change that default to main in Git 3.0. One setting, init.defaultBranch, removes both the old name
and the hint for every repository you create from now on. It changes nothing in repositories that already exist.
git config get --show-scope --show-origin then says where the value came from: the global scope, the file
~/.gitconfig in your home folder. Some installers set this for you, which is why the hint never appears for some
people: the same git config get command shows which file set it.
Tell Git who you are
user.name is your personal name, the way people refer to you, such as “Asha Rao”. It is not a login and has no effect
on signing in to any service. user.email is the address that goes into every commit, and anyone who can see the
repository can read it, so for public repositories use an address you are happy to publish. GitHub offers each account a
no-reply address for exactly this purpose; commits already made keep the address they were made with.
If you skip these settings, Git guesses. It falls back to the EMAIL environment variable and then to your account name
and the computer’s network name. Depending on the computer, it then either stops with “unable to auto-detect email
address” or commits with an address made from those names, such as asha@asha-laptop.lan, which nobody can reply to.
The setting user.useConfigOnly turns the guess off: with it, Git refuses to commit until both values are set, which is
what this session shows first:
from gitsession import session
session(r"""
git config set --global init.defaultBranch main
# Never guess a name or an email: refuse to commit until both are set
git config set --global user.useConfigOnly true
git init -q notes
cd notes
printf 'Buy chart paper\n' > todo.txt
git add todo.txt
! git commit -q -m "Start a to-do list"
git config set --global user.name "Asha Rao"
git config set --global user.email "asha.rao@example.com"
git commit -q -m "Start a to-do list"
git log --format='%h %an <%ae>: %s'
# The same key again, for this repository only
git config set user.email "asha@college.example.edu"
git config list --show-scope --show-origin
git config get --show-scope --show-origin user.email
""") Output
$ git config set --global init.defaultBranch main # Never guess a name or an email: refuse to commit until both are set $ git config set --global user.useConfigOnly true $ git init -q notes $ cd notes $ printf 'Buy chart paper\n' > todo.txt $ git add todo.txt $ git commit -q -m "Start a to-do list" Author identity unknown *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository. fatal: no email was given and auto-detection is disabled [exit status 128] $ git config set --global user.name "Asha Rao" $ git config set --global user.email "asha.rao@example.com" $ git commit -q -m "Start a to-do list" $ git log --format='%h %an <%ae>: %s' 8b7f734 Asha Rao <asha.rao@example.com>: Start a to-do list # The same key again, for this repository only $ git config set user.email "asha@college.example.edu" $ git config list --show-scope --show-origin global file:~/.gitconfig init.defaultbranch=main global file:~/.gitconfig user.useconfigonly=true global file:~/.gitconfig user.name=Asha Rao global file:~/.gitconfig user.email=asha.rao@example.com local file:.git/config core.repositoryformatversion=0 local file:.git/config core.filemode=true local file:.git/config core.bare=false local file:.git/config core.logallrefupdates=true local file:.git/config core.ignorecase=true local file:.git/config core.precomposeunicode=true local file:.git/config user.email=asha@college.example.edu $ git config get --show-scope --show-origin user.email local file:.git/config asha@college.example.edu
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 identity.py
The refused commit asks for user.email and user.name, and once both are set, git log shows them in the commit. The
last part sets user.email a second time without --global, so it goes into this repository’s own file, .git/config.
git config set is the current spelling: Git 2.46 replaced the old mode options with subcommands such as list, get
and set. The older form, git config --global user.name "Asha Rao", still works, and you will see it in many guides
and in Git’s own messages, such as the one in the refused commit.
Where settings live, and which one wins
Git reads its settings from several files, one after another, and for a setting with one value the last value it finds wins. Each level therefore overrides the ones before it:
The levels of Git settings, from the weakest to the strongest
Text description of the diagram
The diagram is a column of five levels. Git reads them from the top down, and for a setting that has one value, the last value it finds wins.
- System: the file /etc/gitconfig (its exact place depends on how Git was installed), for every user of the computer, written with git config set --system.
- Global: ~/.gitconfig in your home folder (or ~/.config/git/config), for you in every repository, written with git config set --global.
- Local: .git/config inside one repository, written with git config set and no level option.
- Worktree: .git/config.worktree, for one working tree of a repository, used only when the repository has turned this file on.
- Command line: git -c name=value before a command, for that one command.
Each level overrides the levels above it, so a local user.email beats the global one inside that repository.
The three levels you will use most:
- System, the file
/etc/gitconfig(its place depends on how Git was installed): settings for every user of the computer, written withgit config set --system, which needs administrator rights. It is for settings an administrator wants everyone to have. - Global, the file
~/.gitconfig(or~/.config/git/config): your settings, for every repository you use, written withgit config set --global. Your name, email, editor, aliases and default branch belong here. - Local, the file
.git/configinside a repository: settings for that repository only, written withgit config setand no level option. It is the place for a different email or setting in one project.
Two more levels exist. A worktree file, .git/config.worktree, applies to one working tree of a repository and is
read only when the repository has turned it on. And git -c name=value sets a value for one command, above all files.
The --show-scope --show-origin list in the session above shows the levels at work. The global lines come from
~/.gitconfig, the local lines from .git/config. The core.* lines were written by git init itself, and two of
them appear only on some systems: git init sets core.ignorecase where the disk does not tell upper from lower case
in file names, as on a Mac, and core.precomposeunicode is used only by Git on macOS, for how the system spells
accented file names. user.email is set at both levels, and inside this repository the local one wins, as
git config get shows.
One email for college, another for everything else
Changing user.email in every new repository by hand is easy to forget. A conditional include does it by folder: an
includeIf section in your global file names another settings file to read, but only for repositories inside a given
folder.
from gitsession import session
session(r"""
git config set --global init.defaultBranch main
git config set --global user.name "Asha Rao"
git config set --global user.email "asha.rao@example.com"
# Repositories anywhere under ~/college/ also read ~/.gitconfig-college
git config set --global includeIf.gitdir:~/college/.path "~/.gitconfig-college"
git config set --file ~/.gitconfig-college user.email "asha@college.example.edu"
cat ~/.gitconfig
cat ~/.gitconfig-college
git init -q college/physics-lab
git init -q personal/blog
cd college/physics-lab
git config get --show-origin user.email
cd ../../personal/blog
git config get --show-origin user.email
""") Output
$ git config set --global init.defaultBranch main $ git config set --global user.name "Asha Rao" $ git config set --global user.email "asha.rao@example.com" # Repositories anywhere under ~/college/ also read ~/.gitconfig-college $ git config set --global includeIf.gitdir:~/college/.path "~/.gitconfig-college" $ git config set --file ~/.gitconfig-college user.email "asha@college.example.edu" $ cat ~/.gitconfig [init] defaultBranch = main [user] name = Asha Rao email = asha.rao@example.com [includeIf "gitdir:~/college/"] path = ~/.gitconfig-college $ cat ~/.gitconfig-college [user] email = asha@college.example.edu $ git init -q college/physics-lab $ git init -q personal/blog $ cd college/physics-lab $ git config get --show-origin user.email file:~/.gitconfig-college asha@college.example.edu $ cd ../../personal/blog $ git config get --show-origin user.email file:~/.gitconfig asha.rao@example.com
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 two_emails.py
gitdir:~/college/ matches every repository whose .git folder is anywhere under ~/college/: the ~ stands for your
home folder, and a pattern that ends with / matches everything inside that folder, however deep. Inside
college/physics-lab, Git also reads ~/.gitconfig-college, and its email, read later, wins; in personal/blog, the
global email applies. Since the include sits in your global file, it works for every repository you clone or create
under that folder from now on. If you prefer to be asked instead, set only user.name globally, add
user.useConfigOnly true, and Git refuses to commit in each new repository until you set its email.
New in Git 2.56
Git 2.56 can also match on the location of the working tree, with an includeIf "worktree:…" condition that
takes the same kind of pattern. Git 2.54, which runs this track’s examples, does not have it.
Aliases, the editor and help
from gitsession import session
session(r"""
git config set --global init.defaultBranch main
git config set --global user.name "Asha Rao"
git config set --global user.email "asha.rao@example.com"
git init -q notes
cd notes
printf 'Buy chart paper\n' > todo.txt
git add todo.txt
git commit -q -m "Start a to-do list"
printf 'Book the physics lab\n' >> todo.txt
git commit -q -am "Add the lab booking"
# An alias: git lg runs a long log command
git config set --global alias.lg "log --oneline --graph --decorate --all"
git lg
# An alias cannot replace a command Git already has
git config set --global alias.status "log --oneline"
git status
# The editor for commit messages, and the one Git will really use
git config set --global core.editor "code --wait"
git var GIT_EDITOR
# Short help for one command
! git init -h
""") Output
$ git config set --global init.defaultBranch main
$ git config set --global user.name "Asha Rao"
$ git config set --global user.email "asha.rao@example.com"
$ git init -q notes
$ cd notes
$ printf 'Buy chart paper\n' > todo.txt
$ git add todo.txt
$ git commit -q -m "Start a to-do list"
$ printf 'Book the physics lab\n' >> todo.txt
$ git commit -q -am "Add the lab booking"
# An alias: git lg runs a long log command
$ git config set --global alias.lg "log --oneline --graph --decorate --all"
$ git lg
* 9dec939 (HEAD -> main) Add the lab booking
* 8b7f734 Start a to-do list
# An alias cannot replace a command Git already has
$ git config set --global alias.status "log --oneline"
$ git status
On branch main
nothing to commit, working tree clean
# The editor for commit messages, and the one Git will really use
$ git config set --global core.editor "code --wait"
$ git var GIT_EDITOR
code --wait
# Short help for one command
$ git init -h
usage: git init [-q | --quiet] [--bare] [--template=<template-directory>]
[--separate-git-dir <git-dir>] [--object-format=<format>]
[--ref-format=<format>]
[-b <branch-name> | --initial-branch=<branch-name>]
[--shared[=<permissions>]] [<directory>]
--[no-]template <template-directory>
directory from which templates will be used
--[no-]bare create a bare repository
--shared[=<permissions>]
specify that the git repository is to be shared amongst several users
-q, --[no-]quiet be quiet
--[no-]separate-git-dir <gitdir>
separate git dir from working tree
-b, --[no-]initial-branch <name>
override the name of the initial branch
--[no-]object-format <hash>
specify the hash algorithm to use
--[no-]ref-format <format>
specify the reference format to use
[exit status 129]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 extras.py
- Aliases shorten long commands:
alias.lgmakesgit lgprint the history as a graph with branch names. An alias cannot replace a command Git already has, so thestatusalias in the session is ignored andgit statusstill runs the real command. The manual explains why: hiding existing commands would confuse scripts. - The editor opens when Git needs you to write a message, for example a commit without
-m.core.editor "code --wait"picks Visual Studio Code;--waitmakes Git wait until you close the file. Other common choices arenanoandvim.git var GIT_EDITORprints the editor Git will actually use. - Help:
git help configopens the full manual of a command, andgit config -hprints its short usage. In Git 2.54, as the session shows,-hends with exit status 129, which a script sees as a failure. Git 2.56 changed most commands to exit with status 0 when you ask for help directly.
Check your settings
Run git config list --show-scope --show-origin in any repository and read it from the bottom up: the last line for a
name is the value Git uses. The exercise below asks you to write that rule as a small Python function and test it with
the sample tests.
Exercise · Easy · Python
Find the value Git uses for a setting
git config list --show-scope prints every setting Git read, in the order it read them, one per line: the scope, a tab, then name=value. For example:
global user.email=asha.rao@example.com
global alias.lg=log --oneline --graph
local user.email=asha@college.example.edu
Write winning_value(listing, name), which takes that output as one string and the name of a setting, and returns a tuple (value, scope) with the value Git uses and the scope it came from, or None when the setting is not there. For the listing above, winning_value(listing, "user.email") returns ("asha@college.example.edu", "local").
Follow Git's rules:
- When a name appears more than once, the last line wins.
- The first part of a name (the section, such as
user) and the last part (the variable, such asemail) are compared without regard to case, soUser.Emailfindsuser.email. A middle part, such asMaininbranch.Main.remote, must match exactly. - A value can contain
=itself (alias.lg=log --format=%h): only the first=of a line separates the name from the value. - Skip empty lines.
Starter code · winner.py
def winning_value(listing, name):
"""Return (value, scope) for the setting `name` in the output of git config list --show-scope, or None."""
return None The sample tests · test_winner.py
from winner import winning_value
def test_later_level_wins():
"""a local value beats the global one"""
listing = "global\tuser.email=asha.rao@example.com\nlocal\tuser.email=asha@college.example.edu\n"
assert winning_value(listing, "user.email") == ("asha@college.example.edu", "local")
def test_not_set():
"""returns None for a setting that is not there"""
listing = "global\tuser.name=Asha Rao\n"
assert winning_value(listing, "user.email") is None
def test_names_ignore_case():
"""section and variable names are compared without case"""
listing = "global\tinit.defaultbranch=main\n"
assert winning_value(listing, "init.defaultBranch") == ("main", "global")
assert winning_value(listing, "INIT.DEFAULTBRANCH") == ("main", "global")
def test_value_with_equals():
"""only the first = separates the name from the value"""
listing = "global\talias.lg=log --format=%h %s\n"
assert winning_value(listing, "alias.lg") == ("log --format=%h %s", "global")
def test_middle_part_is_exact():
"""a subsection must match exactly"""
listing = "local\tbranch.Main.remote=origin\n"
assert winning_value(listing, "BRANCH.Main.REMOTE") == ("origin", "local")
assert winning_value(listing, "branch.main.remote") is None
def test_same_file_twice():
"""the last line wins, even within one file"""
listing = "global\tcore.editor=nano\n\nglobal\tcore.editor=code --wait\n"
assert winning_value(listing, "core.editor") == ("code --wait", "global") A hint
Go through the lines in order and remember the last one whose name matches; there is no need to sort anything. line.partition("\t") splits a line once, at the tab, and setting.partition("=") splits once, at the first =. To compare names, rewrite both in one standard form: the section and the variable in lower case, a middle part as it is. name.partition(".") gives the section, and rest.rpartition(".") the middle part and the variable.
Results of the sample tests
| Test | Result | Details |
|---|
What your code printed
The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.
Check yourself
6 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
Run the sessions yourself
The sessions above use the same helper as the first lesson of this track, gitsession.py. It gives every session a new,
empty home folder, so the git config set --global lines there change only that folder, never your own ~/.gitconfig.
To replay one on macOS or Linux, keep gitsession.py beside the session file and run, for example,
python3 identity.py.
"""Plays a terminal session with real Git: each command is printed after "$ ", then everything it printed.
The session runs in a new, empty folder called learner/, which is also its home folder, so your own Git settings
change nothing, and GIT_CONFIG_NOSYSTEM=1 makes Git skip the computer's system-wide settings file too. Git never
looks for a repository above that folder, so a session cannot touch a repository you run it from. In the output,
"~" stands for that folder. Commit times are fixed, because a commit's ID covers the time it was made: with the
same files, message, name and time, every run makes the same commit IDs.
Each line of a script is one /bin/sh command (macOS and Linux), except "cd", which the session does itself. A line
that starts with "# " is printed as a comment. A command written as "! command" is meant to fail: its exit status
is printed and the session goes on. Any other command that fails stops the session with exit status 1.
"""
import os
import shutil
import subprocess
import sys
from pathlib import Path
HOME = Path("learner").resolve()
# One fixed moment in Git's own date format: seconds since 1970, then the time zone (India, UTC+05:30).
FIXED_TIME = "@1767240000 +0530"
def _environment():
# Git's own folder comes first, so every command runs that Git directly (on macOS, /usr/bin/git is a small
# launcher that looks Git up again on every call).
git_folder = subprocess.run(["git", "--exec-path"], capture_output=True, text=True, check=True).stdout.strip()
env = {
"PATH": os.pathsep.join([git_folder, os.environ.get("PATH", "/usr/bin:/bin")]),
"HOME": str(HOME),
"XDG_CONFIG_HOME": str(HOME / ".config"),
"GIT_CONFIG_NOSYSTEM": "1",
"GIT_CEILING_DIRECTORIES": str(HOME.parent),
"GIT_AUTHOR_DATE": FIXED_TIME,
"GIT_COMMITTER_DATE": FIXED_TIME,
"LANG": "C",
"LC_ALL": "C",
"TERM": "dumb",
}
if "TMPDIR" in os.environ:
env["TMPDIR"] = os.environ["TMPDIR"]
return env
def _with_tilde(text):
"""Writes the home folder as "~", however the operating system spells its path."""
for spelling in sorted({str(HOME), os.path.realpath(HOME)}, key=len, reverse=True):
text = text.replace(spelling, "~")
return text
def session(script):
"""Runs the script's commands one by one, starting in an empty home folder."""
shutil.rmtree(HOME, ignore_errors=True)
HOME.mkdir()
env = _environment()
folder = HOME
for line in script.strip().splitlines():
command = line.strip()
if not command:
continue
if command.startswith("# "):
print(command)
continue
meant_to_fail = command.startswith("! ")
if meant_to_fail:
command = command[2:]
print("$", command)
if command.startswith("cd "):
folder = (folder / command[3:].strip()).resolve()
continue
done = subprocess.run(command, shell=True, cwd=folder, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
print(_with_tilde(done.stdout), end="")
if done.returncode != 0:
print(f"[exit status {done.returncode}]")
if not meant_to_fail:
sys.exit(1)
elif meant_to_fail:
sys.exit(f"{command} was meant to fail, but it worked") Interview questions
When the same setting is in your global file and in a repository’s local file, which one does Git use?
Inside that repository, the local one. Git reads its settings files in a fixed order, system first, then global, then
local, then the worktree file when it is turned on, and for a setting with one value the last value it finds wins, so
each level overrides the ones before it. A git -c name=value option on the command line beats them all, for that one
command. Outside the repository, the local file is not read, so the global value applies. To check instead of reasoning,
run git config get --show-scope --show-origin user.email in the repository: it prints the winning value with the scope
and the file it came from. git config list --show-scope --show-origin prints every value Git read, in order, so the
last line for a name is the one in use.
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Fresher to mid
You commit to college projects and to personal open-source projects from one laptop, and your college asks you to use its address for its repositories. Set up Git so that every repository gets the right email without you having to remember, and explain how you would prove that it works.
-
Fresher to mid
A new teammate's first five commits, already pushed, show the author learner with an address ending in .local, and the hosting service links them to no account. Explain what happened, how to fix future commits, and what you would do about the five commits that are already pushed.
Key takeaways
- Install Git for Windows, Apple’s command line tools or a package manager, then check with
git --version. - Set
user.name,user.emailandinit.defaultBranch mainonce withgit config set --global; the email is visible to anyone who can read your commits. - Settings are read system, global, local, worktree, then
git -c; the last value found wins. git config list --show-scope --show-originandgit config get --show-originsay where each value comes from.includeIf "gitdir:~/college/"switches your email for every repository in a folder;user.useConfigOnlymakes Git ask instead of guessing.- Aliases cannot replace built-in commands;
core.editorsets the message editor andgit var GIT_EDITORshows it.
References
- Install Git on Windows (The Git project)
- Install Git on macOS (The Git project)
- Install Git on Linux (The Git project)
- Git for Windows (Git BASH) (The Git for Windows project)
- The Git for Windows installer (its wizard pages) (The Git for Windows project)
- git-config manual (files, scopes, includes, user.*, alias.*, core.editor) (The Git project)
- git-init manual (--initial-branch and init.defaultBranch) (The Git project)
- git-commit manual (commit information) (The Git project)
- git-var manual (GIT_EDITOR) (The Git project)
- Visual Studio Code command line (the --wait option) (Visual Studio Code project)
- gitfaq (what to put in user.name) (The Git project)
- Setting your commit email address (GitHub)
- Git 2.46.0 release notes (git config subcommands) (The Git project)
- Git 2.56.0 release notes (The Git project)
- Upcoming breaking changes (Git 3.0) (The Git project)
Report a problem with this lesson
Kept only in this browser. Your Learn progress