Learning Objectives
By the end of this module, you will be able to:
- Install Git on macOS, Linux, and Windows using the recommended method for each platform
- Configure Git with your identity, editor, and essential settings at the correct scope level
- Generate SSH keys (RSA and Ed25519), understand how they work, and register them with GitHub
- Choose between HTTPS and SSH authentication and configure credential helpers
- Verify your setup with a successful clone from GitHub
1. Installing Git
macOS
macOS ships with a Git binary as part of the Xcode Command Line Tools. Open Terminal and run:
git --versionIf Git isn't installed, macOS will prompt you to install the Command Line Tools. Click Install and wait.
Alternatively, install via Homebrew (recommended for keeping Git up to date):
brew install gitAfter installation, verify:
git --version
# git version 2.44.0 (or similar)Note: The Apple-shipped Git tends to lag behind. If you want the latest features, use Homebrew.
Linux (Debian/Ubuntu)
The default package manager usually has Git, but often an older version:
sudo apt update
sudo apt install git
git --versionTo get the latest stable version, add the official PPA:
sudo add-apt-repository ppa:git-core/ppa
sudo apt update
sudo apt install git
git --version
# git version 2.44.0 (or similar)Linux (Fedora/RHEL)
sudo dnf install gitLinux (Arch)
sudo pacman -S gitWindows
Windows offers three main approaches:
Option A: Git for Windows (recommended for beginners)
Download from git-scm.com. The installer includes:
- Git Bash — a terminal emulator that provides a Unix-like shell on Windows
- The Git command-line tools
- An SSH client (
ssh-keygen,ssh-agent) - A credential manager for HTTPS authentication
Key installer choices:
| Setting | Recommended Choice |
|---|---|
| Default editor | Your preferred editor (VS Code, Vim, etc.) |
| Initial branch name | main |
| PATH adjustment | "Git from the command line and also from 3rd-party software" |
| SSH executable | Use bundled OpenSSH |
| HTTPS backend | Use OpenSSL |
| Line endings | "Checkout Windows-style, commit Unix-style" |
| Terminal emulator | MinTTY |
Default git pull behavior | Rebase (we'll explain why in Module 9) |
| Credential helper | Git Credential Manager |
Option B: WSL2 (recommended for serious development on Windows)
The Windows Subsystem for Linux lets you run a full Linux distribution inside Windows. Install it, then install Git inside the Linux distribution using the Linux instructions above. This gives you the exact same environment as a Linux or macOS developer.
# From PowerShell (admin)
wsl --install -d UbuntuThen inside Ubuntu:
sudo apt update && sudo apt install gitOption C: Scoop or Chocolatey
# Scoop
scoop install git
# Chocolatey
choco install gitVerify Installation (All Platforms)
git --version
git help -a # List all available commands2. git config — The Three Levels
Before you use Git, you need to tell it who you are. Git stores configuration at three levels, each overriding the one above it:
┌─────────────────────────────────────────┐
│ System /etc/gitconfig │ Applies to all users on this machine
│ (rarely touched) │
├─────────────────────────────────────────┤
│ Global ~/.gitconfig │ Applies to all repos for YOUR user
│ (your personal defaults) │
├─────────────────────────────────────────┤
│ Local .git/config │ Applies to THIS repo only
│ (per-project overrides) │
└─────────────────────────────────────────┘
Precedence: Local > Global > System
Setting Values
# Global (most common — sets your identity for all repos)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Local (override for a specific repo — e.g., work email for work projects)
git config --local user.name "Your Work Name"
git config --local user.email "you@company.com"
# System (rarely used — affects all users)
sudo git config --system core.autocrlf inputReading Values
# Show a single value
git config user.name
# Show where a value comes from
git config --show-origin user.name
# List all settings and their origins
git config --list --show-origin
# List only global settings
git config --global --listEditing the Config File Directly
git config --global --edit # Opens ~/.gitconfig in your editor
git config --local --edit # Opens .git/config in your editorThe config file uses INI-style syntax:
[user]
name = Your Name
email = you@example.com
[core]
editor = vim
autocrlf = input
[init]
defaultBranch = main3. Essential Configuration Settings
Run these commands once after installing Git. These are your global defaults.
Identity (required)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"Every commit you make is stamped with this name and email. Use the email associated with your GitHub account so that GitHub links commits to your profile.
Important: If you contribute to both personal and work projects, use
--localconfig in work repos to set your work email there. Your global config will apply everywhere else.
Default Editor
Git opens a text editor for commit messages, interactive rebase, and other operations. Set it to your preferred editor:
# VS Code (waits for you to close the file)
git config --global core.editor "code --wait"
# Vim
git config --global core.editor "vim"
# Neovim
git config --global core.editor "nvim"
# Nano (beginner-friendly)
git config --global core.editor "nano"
# Sublime Text
git config --global core.editor "subl -n -w"The --wait flag (for GUI editors) tells Git to wait until you save and close the file before proceeding.
Default Branch Name
git config --global init.defaultBranch mainWhen you run git init, the first branch will be called main instead of the legacy master.
Line Endings
Different operating systems use different characters to mark line endings:
- Unix/macOS:
LF(line feed,\n) - Windows:
CRLF(carriage return + line feed,\r\n)
This causes problems in mixed teams. Configure Git to normalize:
# macOS / Linux: convert CRLF to LF on commit, no conversion on checkout
git config --global core.autocrlf input
# Windows: convert LF to CRLF on checkout, CRLF to LF on commit
git config --global core.autocrlf truePull Behavior
git config --global pull.rebase trueThis tells git pull to rebase your local changes on top of remote changes instead of creating a merge commit. We'll explain why this produces cleaner history in Module 9.
Colored Output
git config --global color.ui autoUsually enabled by default on modern Git. Makes output of git diff, git status, git log, etc. much more readable.
Useful Extras
# Show untracked files in subdirectories (not just the directory name)
git config --global status.showUntrackedFiles all
# Always show the commit summary in merge commits
git config --global merge.log true
# Use patience diff algorithm (better at handling moved code blocks)
git config --global diff.algorithm patience4. SSH Keys: How They Work
SSH keys are a method of authentication based on public-key cryptography. Instead of typing a password every time you interact with GitHub, you prove your identity using a key pair.
The Key Pair
┌──────────────────┐ ┌──────────────────┐
│ Private Key │ │ Public Key │
│ │ │ │
│ id_ed25519 │ │ id_ed25519.pub │
│ │ │ │
│ STAYS ON YOUR │ │ SHARED WITH │
│ MACHINE. │ │ GITHUB (and │
│ NEVER SHARE. │ │ anyone else). │
│ │ │ │
│ Like the key │ │ Like the lock │
│ to your house. │ │ on your door. │
└──────────────────┘ └──────────────────┘
The authentication flow:
- You try to connect to GitHub via SSH
- GitHub has your public key on file
- GitHub generates a challenge — a random message encrypted using your public key
- Only your private key can decrypt it
- Your machine decrypts the challenge and responds
- GitHub verifies the response — you're authenticated
At no point is your private key transmitted. The security depends on keeping the private key secret.
RSA vs. Ed25519
| Property | RSA | Ed25519 |
|---|---|---|
| Year introduced | 1977 | 2011 |
| Cryptographic basis | Integer factorization | Elliptic curves |
| Default key size | 3072 bits | 256 bits (fixed) |
| Recommended key size | 4096+ bits | 256 bits (no choice needed) |
| Key length (text) | ~400+ characters | ~68 characters |
| Performance | Slower for large keys | Very fast |
| Security at equivalent key size | Good | Better |
| Legacy compatibility | Universal | Some very old systems don't support it |
Recommendation: Use Ed25519 unless you need to connect to very old systems that only support RSA. Ed25519 keys are shorter, faster, and more secure at equivalent strength.
Generating an Ed25519 Key
ssh-keygen -t ed25519 -C "you@example.com"You'll be asked:
- File location — press Enter to accept the default (
~/.ssh/id_ed25519) - Passphrase — enter a strong passphrase (this encrypts the private key on disk, so even if someone steals the file, they can't use it without the passphrase)
Output:
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/you/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/you/.ssh/id_ed25519
Your public key has been saved in /home/you/.ssh/id_ed25519.pub
Generating an RSA Key (if needed)
ssh-keygen -t rsa -b 4096 -C "you@example.com"The -b 4096 sets the key size to 4096 bits (more secure than the default 3072).
What's in Your .ssh Directory
ls -la ~/.ssh/drwx------ 2 you you 4096 Jan 15 10:00 . ← directory: 700
-rw------- 1 you you 464 Jan 15 10:00 id_ed25519 ← private key: 600
-rw-r--r-- 1 you you 97 Jan 15 10:00 id_ed25519.pub ← public key: 644
-rw-r--r-- 1 you you 444 Jan 15 10:00 known_hosts ← servers you've connected to
Permissions matter. SSH refuses to use keys with overly permissive permissions. If you ever copy keys between machines, fix permissions:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 # private key: owner read/write only
chmod 644 ~/.ssh/id_ed25519.pub # public key: owner read/write, others readViewing Your Public Key
cat ~/.ssh/id_ed25519.pubOutput (one line):
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... you@example.com
This is what you copy to GitHub.
5. Adding Your SSH Key to GitHub
-
Copy your public key to the clipboard:
# macOS pbcopy < ~/.ssh/id_ed25519.pub # Linux (requires xclip) xclip -selection clipboard < ~/.ssh/id_ed25519.pub # WSL / manual cat ~/.ssh/id_ed25519.pub # Then select and copy the output -
Go to GitHub → Settings → SSH and GPG keys (or navigate directly to
github.com/settings/keys) -
Click New SSH key
-
Give it a descriptive Title (e.g., "MacBook Pro 2024", "Work Laptop Ubuntu")
-
Paste your public key into the Key field
-
Click Add SSH key
Testing the Connection
ssh -T git@github.comExpected output:
Hi yourusername! You've successfully authenticated, but GitHub does not provide shell access.
The first time you connect, SSH will ask you to verify GitHub's fingerprint:
The authenticity of host 'github.com (IP)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Type yes. This adds GitHub to your ~/.ssh/known_hosts file so it won't ask again.
6. SSH Agent and Credential Management
If you set a passphrase on your SSH key (you should), you'll be asked for it every time Git connects to GitHub. An SSH agent caches your unlocked key in memory so you only enter the passphrase once per session.
macOS
macOS has a built-in SSH agent integrated with Keychain. Add this to ~/.ssh/config:
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
Then add your key:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519The passphrase is stored in macOS Keychain — you won't be asked again, even after a reboot.
Linux
Start the agent and add your key:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519This lasts until the session ends. For persistent caching, use keychain:
# Install
sudo apt install keychain # Debian/Ubuntu
sudo dnf install keychain # Fedora
# Add to ~/.bashrc or ~/.zshrc
eval $(keychain --eval --quiet --nogui ~/.ssh/id_ed25519)With keychain, you enter your passphrase once after login and it stays cached for the entire session.
Windows (Git for Windows)
Git for Windows includes a credential manager that handles HTTPS authentication automatically. For SSH, Git Bash includes an ssh-agent. Add to your ~/.bashrc:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519WSL2
SSH agent doesn't persist between WSL sessions by default. Use keychain (same as Linux instructions above).
7. HTTPS vs. SSH Authentication
When you clone a repository from GitHub, you choose a protocol:
HTTPS
git clone https://github.com/org/repo.git- Authenticates with a personal access token (PAT) — GitHub no longer accepts passwords
- Works through corporate firewalls and proxies (port 443)
- Requires a credential helper to avoid re-entering the token
Setting up a credential helper:
# macOS (uses Keychain)
git config --global credential.helper osxkeychain
# Linux (caches in memory for 1 hour)
git config --global credential.helper 'cache --timeout=3600'
# Linux (stores permanently in a file — less secure)
git config --global credential.helper store
# Windows (Git Credential Manager — installed with Git for Windows)
git config --global credential.helper managerSSH
git clone git@github.com:org/repo.git- Authenticates with your SSH key pair
- No tokens to manage or rotate
- Uses port 22 (may be blocked by some firewalls)
- Requires initial SSH key setup (once)
Which Should You Choose?
| Factor | HTTPS | SSH |
|---|---|---|
| Initial setup | Simpler (token-based) | Requires key generation + registration |
| Daily usage | May need credential helper | Seamless once agent is running |
| Corporate networks | Works through proxies | Port 22 may be blocked |
| Security | Token can be scoped and rotated | Key pair — no secrets transmitted |
| Multiple accounts | Awkward (credentials per URL) | Clean (config per Host) |
Recommendation: Use SSH for your daily workflow. It's more secure and more convenient once set up. Fall back to HTTPS if SSH port 22 is blocked.
Checking Which Protocol a Clone Uses
git remote -vorigin git@github.com:org/repo.git (fetch) ← SSH
origin git@github.com:org/repo.git (push)
origin https://github.com/org/repo.git (fetch) ← HTTPS
origin https://github.com/org/repo.git (push)
You can switch an existing clone from HTTPS to SSH (or vice versa):
# Switch to SSH
git remote set-url origin git@github.com:org/repo.git
# Switch to HTTPS
git remote set-url origin https://github.com/org/repo.git8. Managing Multiple SSH Keys
If you have multiple GitHub accounts (personal + work) or connect to multiple services (GitHub + GitLab + Bitbucket), you need multiple SSH keys.
Generate a Separate Key for Each
ssh-keygen -t ed25519 -C "personal@example.com" -f ~/.ssh/id_ed25519_personal
ssh-keygen -t ed25519 -C "work@company.com" -f ~/.ssh/id_ed25519_workConfigure ~/.ssh/config
# Personal GitHub
Host github.com-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
# Work GitHub
Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
# GitLab
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_ed25519_work
Clone Using the Alias
# Personal
git clone git@github.com-personal:myuser/personal-project.git
# Work
git clone git@github.com-work:company/work-project.gitGit connects to github.com in both cases, but SSH uses the correct key based on the Host alias.
9. Configuring Your Editor for Git
VS Code
git config --global core.editor "code --wait"VS Code will open a new tab for commit messages. Save and close the tab to continue.
Useful VS Code extensions for Git:
- GitLens — inline blame, rich history exploration
- Git Graph — visual commit graph
Vim / Neovim
git config --global core.editor "vim" # or "nvim"When Git opens Vim for a commit message:
ito enter insert mode, type your messageEscthen:wqto save and quitEscthen:q!to abort (empty message = aborted commit)
Diff and Merge Tools
You can also configure external tools for diffs and merge conflict resolution:
# VS Code as diff tool
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
# VS Code as merge tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'We'll use these in Modules 7 and 14.
Command Reference
| Command | Description |
|---|---|
git --version | Show the installed Git version |
git help <command> | Open the manual page for a command |
git config --global <key> <value> | Set a global configuration value |
git config --local <key> <value> | Set a repo-level configuration value |
git config --list --show-origin | List all config values and where they're defined |
git config --global --edit | Open the global config file in your editor |
git clone <url> | Clone a remote repository to your machine |
git clone <url> <directory> | Clone into a specific directory name |
git remote -v | Show remote URLs (fetch and push) |
git remote set-url origin <url> | Change the remote URL |
ssh-keygen -t ed25519 -C "email" | Generate an Ed25519 SSH key pair |
ssh-keygen -t rsa -b 4096 -C "email" | Generate a 4096-bit RSA key pair |
ssh -T git@github.com | Test SSH connection to GitHub |
ssh-add ~/.ssh/id_ed25519 | Add a key to the SSH agent |
Hands-On Lab: Full Setup from Scratch
This lab walks you through a complete Git setup. Even if you already have Git configured, follow along — it's a useful opportunity to audit your settings.
Prerequisites
- A GitHub account (create one at github.com if you don't have one)
- A terminal (Terminal on macOS, any terminal on Linux, Git Bash or WSL on Windows)
Step 1: Install Git
Follow the instructions for your OS in Section 1 above.
Checkpoint:
git --versionYou should see a version number (2.30+ recommended).
Step 2: Set Your Identity
git config --global user.name "Your Full Name"
git config --global user.email "your-github-email@example.com"Checkpoint:
git config --global user.name
git config --global user.emailBoth should print the values you just set.
Step 3: Configure Essential Settings
git config --global init.defaultBranch main
git config --global core.editor "code --wait" # or vim, nano, etc.
git config --global pull.rebase true
git config --global color.ui autoOn macOS/Linux:
git config --global core.autocrlf inputOn Windows (Git Bash or PowerShell, not WSL):
git config --global core.autocrlf trueCheckpoint:
git config --global --listYou should see all the settings you've configured.
Step 4: Generate an SSH Key
ssh-keygen -t ed25519 -C "your-github-email@example.com"- Press Enter to accept the default file location
- Enter a passphrase (recommended) and confirm it
Checkpoint:
ls -la ~/.ssh/You should see id_ed25519 and id_ed25519.pub.
Step 5: Start the SSH Agent
macOS:
# Create or edit ~/.ssh/config
cat >> ~/.ssh/config << 'EOF'
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
EOF
ssh-add --apple-use-keychain ~/.ssh/id_ed25519Linux / WSL:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519Enter your passphrase when prompted.
Step 6: Add Your Public Key to GitHub
cat ~/.ssh/id_ed25519.pubCopy the entire output (one line, starting with ssh-ed25519).
- Go to github.com → Settings → SSH and GPG keys
- Click New SSH key
- Title: give it a name (e.g., "My Laptop")
- Paste the key
- Click Add SSH key
Step 7: Test the Connection
ssh -T git@github.comType yes if asked about the host fingerprint.
Checkpoint: You should see:
Hi yourusername! You've successfully authenticated, but GitHub does not provide shell access.
Step 8: Clone a Repository
Go to any repository on GitHub (e.g., one you created in Module 1's discussion of GitHub). Click Code → SSH and copy the URL.
mkdir -p ~/dev
cd ~/dev
git clone git@github.com:your-username/your-repo.gitCheckpoint:
cd your-repo
git remote -vYou should see:
origin git@github.com:your-username/your-repo.git (fetch)
origin git@github.com:your-username/your-repo.git (push)
Step 9: Verify Everything Together
# Show your full config
git config --list --show-origin | head -20
# Show the remote
git remote -v
# Show the branch
git branch
# Show the log (if the repo has commits)
git log --onelineStep 10: Intentional Mistake — Wrong Permissions
Let's break SSH on purpose to understand what happens.
chmod 777 ~/.ssh/id_ed25519
ssh -T git@github.comYou'll see an error like:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/home/you/.ssh/id_ed25519' are too open.
SSH refuses to use a private key that other users can read. Fix it:
chmod 600 ~/.ssh/id_ed25519
ssh -T git@github.comCheckpoint: The Hi yourusername! message should return.
Challenge
- Generate a second SSH key (RSA, 4096 bits) and add it to GitHub alongside your Ed25519 key
- Create an
~/.ssh/configfile with twoHostentries pointing togithub.com— one using each key - Clone the same repository twice using each host alias, and verify with
git remote -vthat each clone uses a different SSH URL
Cleanup
If you generated test keys you don't need:
rm ~/.ssh/id_rsa ~/.ssh/id_rsa.pub # remove RSA test keysCommon Pitfalls & Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
ssh: connect to host github.com port 22: Connection refused | Port 22 blocked (corporate firewall) | Use SSH over HTTPS port: add Host github.com / Port 443 / HostName ssh.github.com to ~/.ssh/config |
Permission denied (publickey) | SSH key not registered with GitHub, or agent not running | Run ssh-add -l to check loaded keys. Re-add with ssh-add. Verify key is on GitHub. |
WARNING: UNPROTECTED PRIVATE KEY FILE | Private key permissions too open | chmod 600 ~/.ssh/id_ed25519 |
| Commit shows wrong email on GitHub | user.email doesn't match your GitHub email | git config --global user.email "correct@email.com" |
git pull creates unnecessary merge commits | Default pull strategy is merge | git config --global pull.rebase true |
| Editor doesn't open for commit messages | core.editor not set or command wrong | Verify with git config --global core.editor. For VS Code, ensure code is in your PATH. |
| HTTPS asks for password every time | No credential helper configured | Set up the credential helper for your OS (see Section 7) |
fatal: not a git repository | You're not inside a cloned repo | cd into the repository directory. Look for a .git subdirectory. |
Pro Tips
-
Audit your config regularly. Run
git config --list --show-originto see every setting and where it comes from. Stale or conflicting settings across system/global/local levels cause subtle bugs. -
Use
--localconfig for work repos. Keep your personal email in--global, and set your work email with--localinside work repositories. Git will use the most specific value. -
Never copy private keys over insecure channels. If you need to move keys between machines, use a USB drive or a secure transfer method. Better yet, generate a new key on each machine and register each with GitHub — you can have many SSH keys.
-
Use descriptive names when registering SSH keys on GitHub. "MacBook Pro 2024" or "Work Desktop Ubuntu" is infinitely better than "my key." When you retire a machine, you'll know which key to revoke.
-
Git Bash on Windows is a lifeline. It gives you
ls,cat,ssh-keygen,grep, and other Unix commands. If you're on Windows and not using WSL, Git Bash is your best friend for following Git tutorials designed for Unix-like systems. -
Check if SSH works over port 443. Many corporate networks block port 22. GitHub supports SSH connections on port 443 via
ssh.github.com. Add this to~/.ssh/config:Host github.com HostName ssh.github.com Port 443 User git
Quiz / Self-Assessment
1. What are the three levels of git config and what is their precedence?
Answer
2. What's the difference between --global and --local config?
Answer
--global applies to all repositories for your user account. --local applies only to the current repository. Use --local to override globals (e.g., setting a work email for work repos).
3. Why should you set a passphrase on your SSH key?
Answer
4. What's the difference between RSA and Ed25519 SSH keys?
Answer
5. What permissions should the ~/.ssh/id_ed25519 (private key) file have, and why?
Answer
600 (owner read/write only). SSH refuses to use private keys that are readable by other users on the system, as that would be a security risk.
6. What does git remote -v show you?
Answer
7. You cloned a repo with HTTPS but want to switch to SSH. What command do you use?
Answer
git remote set-url origin git@github.com:org/repo.git
8. What does git config --global pull.rebase true do?
Answer
git pull use rebase instead of merge by default. Instead of creating a merge commit when pulling remote changes, Git will replay your local commits on top of the remote changes, resulting in a linear history.
9. How do you handle multiple GitHub accounts (personal and work) with SSH?
Answer
~/.ssh/config with different Host aliases (e.g., github.com-personal, github.com-work) that point to the same HostName (github.com) but use different IdentityFile values. Clone using the alias: git clone git@github.com-personal:user/repo.git.
10. What does ssh -T git@github.com do?
Answer
-T flag disables terminal allocation (since GitHub doesn't provide shell access). A successful connection returns "Hi username! You've successfully authenticated..."