Git Installation and Configuration¶
Overview¶
Before your first meaningful commit reaches a CI pipeline, Git must be installed correctly and configured consistently. Wrong author emails break compliance audits. Missing SSH keys block pushes from automation runners. A misconfigured credential helper leaks tokens into logs. Platform engineers onboarding hundreds of developers standardize Git installation and config the same way they standardize base AMIs and container images.
This tutorial covers installing Git across environments, setting identity and defaults, configuring SSH and HTTPS authentication, tuning performance settings for large monorepos, and applying security-conscious options used in production DevOps teams.
This is Tutorial 2 in Module 1: Foundations of the REBASH Academy Git series. Complete Introduction to Git and Version Control first. Linux package management and SSH fundamentals from the Linux track and Networking track apply directly here.
Prerequisites¶
- Completion of Introduction to Git and Version Control
- A Linux environment (Ubuntu 22.04+ recommended) or macOS with terminal access
sudoprivileges for package installation on Linux- Network access to download packages and reach Git hosting providers
- Familiarity with Essential Linux Commands — especially editing files and managing permissions
Learning Objectives¶
By the end of this tutorial, you will be able to:
- Install Git on Debian/Ubuntu, RHEL-family, and macOS using official or PPA sources
- Verify installation and locate the Git binary and system configuration files
- Configure global and repository-local identity (
user.name,user.email) - Set productive defaults: default branch, editor, pull behavior, and whitespace handling
- Generate SSH key pairs and register them with GitHub or GitLab
- Configure HTTPS credential helpers securely for automation and interactive use
- Understand configuration precedence: system, global, local, and environment variables
- Apply a production-ready
.gitconfigbaseline for DevOps engineers
Architecture Diagram¶
Git configuration flows through four layers. Later layers override earlier ones — a common source of "I changed my email but commits still show the old one" confusion.
flowchart TB
ENV["Environment variables<br/>GIT_AUTHOR_NAME, GIT_DIR, ..."]
SYS["System config<br/>/etc/gitconfig"]
GLOBAL["Global config<br/>~/.gitconfig"]
LOCAL["Local config<br/>.git/config"]
CMD["Command-line flags<br/>--author, -c key=value"]
SYS --> GLOBAL
GLOBAL --> LOCAL
LOCAL --> ENV
ENV --> CMD
CMD -->|"wins for this invocation"| EFFECT[Effective config value]
LOCAL --> EFFECT
GLOBAL --> EFFECT
SYS --> EFFECT
ENV --> EFFECT```
## Theory
### Installation Sources and Version Pinning
Git releases frequently — security fixes and performance improvements land in minor versions. Production teams pin minimum versions in documentation (e.g., "Git ≥ 2.34") and CI base images.
| Platform | Recommended method | Notes |
|----------|-------------------|-------|
| Ubuntu/Debian | `apt` or Git PPA | Distro packages may lag; PPA provides latest stable |
| RHEL/Rocky/Alma | `dnf install git` | AppStream module versions vary by release |
| macOS | Xcode CLT or Homebrew | `git --version` after CLT may be older; Homebrew is newer |
| Windows | Git for Windows installer | Includes Git Bash; use WSL2 for Linux parity in DevOps |
| Containers | Base image + `apt-get install git` | Pin in Dockerfile; avoid `latest` tag drift |
For DevOps CI images, install Git in the Dockerfile layer and verify with `git --version` in a health check step. Alpine uses `apk add git`; ensure OpenSSH client is present if using SSH remotes.
### Identity Configuration
Every commit records **author** and **committer** name and email. These fields are immutable in the object once committed (without history rewrite). Use:
- **Corporate email** for work repositories — enables GitHub/GitLab account linking and audit trails
- **noreply addresses** (e.g., `123456+user@users.noreply.github.com`) when privacy settings require hiding personal email
- **Consistent bot identities** for automation: `ci-bot@company.com` with clear display name `CI Bot`
Never use fake emails like `admin@localhost` in shared repos — they break `git blame` and code ownership tools.
### The Three Configuration Scopes
```bash
git config --system # /etc/gitconfig — all users on machine (requires root)
git config --global # ~/.gitconfig — current user's default
git config --local # .git/config — single repository only Precedence (highest wins): command-line → local → global → system → built-in defaults.
Repository-local config overrides global — useful when a contractor uses a personal email globally but a corporate email for one client repo.
Essential Settings for DevOps¶
| Setting | Recommended value | Why |
|---|---|---|
init.defaultBranch | main | Industry standard; avoids renaming later |
pull.rebase | false (teams vary) | Document team policy; rebase keeps linear history |
fetch.prune | true | Removes stale remote-tracking branches after fetch |
core.autocrlf | input (Linux/macOS) | Prevents CRLF corruption in shell scripts and Terraform |
core.editor | vim, nano, or code --wait | Required for interactive rebase and commit amend |
color.ui | auto | Readable diffs in terminal |
push.default | simple | Push current branch to matching remote branch only |
rebase.autoStash | true | Stash local changes before rebase automatically |
SSH vs HTTPS Authentication¶
| Method | Pros | Cons | DevOps use case |
|---|---|---|---|
| SSH | Key-based, no password prompts, works with deploy keys | Key management overhead | Developer laptops, dedicated CI deploy keys |
| HTTPS | Firewall-friendly (port 443), PAT/OAuth tokens | Tokens expire; credential storage risk | Corporate proxies, short-lived CI tokens |
SSH uses git@github.com:org/repo.git. Keys live in ~/.ssh/; ssh-agent holds passphrases during sessions.
HTTPS uses https://github.com/org/repo.git. Personal Access Tokens (PATs) replace passwords. Store via credential.helper — never commit tokens to repos.
For production CI, prefer short-lived OIDC tokens (GitHub Actions → AWS) or machine users with scoped PATs rotated on schedule.
Credential Helpers¶
Git credential helpers cache or store HTTPS credentials:
cache— memory cache with timeout (default 15 minutes)store— plaintext file~/.git-credentials(avoid on shared machines)manager/osxkeychain— OS keychain integration (preferred on workstations)- Custom helpers — enterprise secret vault integration
In CI, inject tokens via environment variables and use:
git config credential.helper '!f() { echo "username=x-access-token"; echo "password=$GITHUB_TOKEN"; }; f'
Never echo tokens in pipeline logs — mask variables in GitHub Actions / GitLab CI settings.
System-Wide and Enterprise Configuration¶
Large organizations deploy /etc/gitconfig via configuration management (Ansible, cloud-init):
The safe.directory setting (Git 2.35+) prevents CVE-2022-24765 issues when repos are owned by different users — common on CI runners and shared build hosts.
Hands-on Lab¶
Perform these steps on your Linux lab machine. Adjust package commands for your distribution.
Step 1 – Check if Git is already installed¶
Command:
Explanation: Cloud images and developer laptops often ship with Git pre-installed. Record the version for your runbook baseline.
Expected output:
Step 2 – Install Git on Ubuntu/Debian¶
Command:
Explanation: Distro packages are sufficient for learning. For the latest stable on Ubuntu, add the git-core PPA only in non-production lab environments.
Expected output:
Step 3 – Configure global identity¶
Command:
git config --global user.name "Shaik Basha"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main
git config --global --list | grep -E 'user\.|init\.'
Explanation: Identity applies to all new commits in repos without local overrides. Use your real work email for corporate projects.
Expected output:
Step 4 – Set editor and useful defaults¶
Command:
git config --global core.editor "nano"
git config --global color.ui auto
git config --global fetch.prune true
git config --global pull.rebase false
git config --global push.default simple
git config --global rebase.autoStash true
Explanation: These defaults match common team policies. Align pull.rebase with your organization's documented workflow.
Expected output:
Step 5 – Generate an SSH key pair¶
Command:
ssh-keygen -t ed25519 -C "you@example.com" -f ~/.ssh/id_ed25519_git -N ""
ls -la ~/.ssh/id_ed25519_git*
cat ~/.ssh/id_ed25519_git.pub
Explanation: Ed25519 keys are modern, compact, and secure. In production, use a passphrase (-N "" is lab-only). Add the public key to GitHub → Settings → SSH Keys.
Expected output:
Step 6 – Configure SSH for Git hosting¶
Command:
cat >> ~/.ssh/config << 'EOF'
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_git
IdentitiesOnly yes
EOF
chmod 600 ~/.ssh/config
ssh -T git@github.com 2>&1 | head -3
Explanation: IdentitiesOnly yes prevents SSH from offering wrong keys. Test connectivity — expect "Hi username!" or "Permission denied" if key not yet added to GitHub.
Expected output:
Step 7 – Inspect configuration precedence¶
Command:
mkdir -p /tmp/git-config-lab && cd /tmp/git-config-lab
git init
git config user.email "local-only@example.com"
git config --show-origin --get user.email
git config --show-origin --get user.name
Explanation: --show-origin reveals which file set each value — essential when debugging wrong identity in commits.
Expected output:
Step 8 – Clean up lab directory¶
Command:
Explanation: Remove test repositories after configuration labs.
Commands & Code¶
| Command | Description | Example |
|---|---|---|
git --version | Verify installation | git --version |
git config --global KEY VAL | Set global option | git config --global user.name "Name" |
git config --list --show-origin | List all settings with source file | git config -l --show-origin |
git config --unset KEY | Remove a setting | git config --global --unset credential.helper |
ssh-keygen -t ed25519 | Create SSH key pair | ssh-keygen -t ed25519 -C "email" |
ssh -T git@github.com | Test SSH auth to GitHub | ssh -T git@github.com |
git config credential.helper | Show credential helper | git config --global credential.helper store |
Production baseline .gitconfig¶
Copy to ~/.gitconfig and customize identity:
[user]
name = Shaik Basha
email = you@company.com
[init]
defaultBranch = main
[core]
editor = nano
autocrlf = input
whitespace = trailing-space,space-before-tab
excludesfile = ~/.gitignore_global
[color]
ui = auto
[fetch]
prune = true
[push]
default = simple
[pull]
rebase = false
[rebase]
autoStash = true
[diff]
algorithm = histogram
[merge]
conflictstyle = zdiff3
[help]
autocorrect = 10
[credential]
helper = cache --timeout=3600
[safe]
directory = *
The safe.directory = * entry is convenient on trusted personal machines; on shared CI runners, list specific paths instead.
Global gitignore template¶
Create ~/.gitignore_global for OS and editor junk:
# OS
.DS_Store
Thumbs.db
# Editors
*.swp
*~
.idea/
.vscode/
# Secrets — never commit
.env
*.pem
credentials.json
Register it: git config --global core.excludesfile ~/.gitignore_global
Common Mistakes¶
Using different emails across machines
Commits from the same human with different emails fragment git shortlog and code ownership reports. Standardize via Ansible/chef and verify with git config --global user.email.
Committing with default 'root' identity on servers
Running git commit as root on production boxes creates useless audit trails. Use deploy keys with bot identity or avoid Git operations on servers entirely — deploy artifacts instead.
Storing PATs in plaintext credential store on shared CI
The store helper writes credentials to disk unencrypted. On shared runners, use ephemeral environment-injected tokens with masked CI variables.
Skipping SSH host key verification
Disabling StrictHostKeyChecking opens MITM attacks. Pre-load known hosts in CI: ssh-keyscan github.com >> ~/.ssh/known_hosts.
Best Practices¶
Pin Git version in CI Dockerfiles
Document git --version in build logs. Unexpected upgrades have changed default behaviors (e.g., safe.directory).
Use separate SSH keys per purpose
One key for personal GitHub, one deploy key per repo (read-only for CI), one for production bastion — limits blast radius if a key leaks.
Configure Git once in golden AMI / container base
Platform teams bake /etc/gitconfig and safe.directory into Jenkins agent AMIs and Kubernetes CI pod images.
Align with Linux SSH hardening
File permissions matter: chmod 700 ~/.ssh, chmod 600 ~/.ssh/id_*. See Linux user management for permission fundamentals.
Troubleshooting¶
| Issue | Cause | Solution |
|---|---|---|
git: command not found after install | PATH not updated in current shell | Open new shell or hash -r; verify /usr/bin/git |
| Commits show wrong email | Local repo override or env var | git config --show-origin --get user.email; check GIT_AUTHOR_EMAIL |
Permission denied (publickey) | Key not loaded or not on GitHub | ssh-add -l; add pubkey to hosting platform; verify IdentityFile |
Support for password authentication was removed | GitHub deprecated password HTTPS | Use PAT or SSH instead |
fatal: unsafe repository | Repo owned by different user (Git 2.35+) | git config --global --add safe.directory /path/to/repo |
| Credential helper not caching | Helper not configured or timeout expired | git config credential.helper 'cache --timeout=86400' |
git commit opens wrong editor | core.editor misconfigured | git config --global core.editor "vim" |
| SSL certificate problem | Corporate MITM proxy or outdated CA | Install corporate CA; or use SSH remotes |
Summary¶
- Install Git from trusted package sources and record version in runbooks and CI images
- Configure identity (
user.name,user.email) before any shared commits — emails are permanent in history unless rewritten - Settings apply in order: system → global → local → environment → CLI flags
- Use SSH keys (Ed25519) for developer workflows; HTTPS + PAT where firewalls require port 443
- Production teams standardize
.gitconfig, global gitignore,safe.directory, and credential handling across the fleet
Interview Questions¶
- What are the three Git configuration scopes, and which takes precedence?
- Why must
user.emailbe configured correctly before your first commit? - Compare SSH and HTTPS authentication for Git remotes.
- What is
init.defaultBranch, and why set it tomain? - How do credential helpers work, and what are the security tradeoffs?
- What is the
safe.directoryconfiguration introduced in Git 2.35? - How would you verify which config file sets a particular Git option?
- What Git settings would you bake into a CI runner base image?
- Why should
core.autocrlfbe set toinputon Linux DevOps workstations? - How do you test SSH connectivity to GitHub without cloning a repository?
Sample Answers (Questions 1, 3, and 6)
Q1 — Config scopes and precedence: System (/etc/gitconfig) applies to all users. Global (~/.gitconfig) applies to the current user. Local (.git/config) applies to one repository. Local overrides global, which overrides system. Command-line flags like -c key=value override all files for that invocation.
Q3 — SSH vs HTTPS: SSH uses public-key authentication (git@host:repo.git). No password prompts once keys are loaded; ideal for developers and deploy keys. HTTPS uses URLs like https://host/repo.git with PATs or OAuth tokens — better through strict corporate proxies on port 443. SSH requires key rotation discipline; HTTPS requires secure token storage and rotation.
Q6 — safe.directory: Git 2.35+ refuses to operate on repositories whose directory is owned by a different user than the one running Git, preventing CVE-2022-24765 exploits on shared systems. CI runners and sudo workflows hit this often. Fix by explicitly trusting paths with git config --global --add safe.directory /path or * on trusted personal machines only.
Related Tutorials¶
- Git – Category Overview
- Introduction to Git and Version Control (previous in Module 1)
- Understanding the Git Object Model (next in Module 1)
- Introduction to Linux
- Introduction to Networking — SSH and HTTPS connectivity