On this page
This Git and GitHub tutorial takes you from a fresh machine to your first push: install Git, set your identity, authenticate with GitHub, protect the repository with .gitignore, then commit and push. Git tracks your file history locally; GitHub hosts a copy so others, and future you, can use it.
Two first-day mistakes cause most of the pain. Typing your GitHub password at the prompt fails, because GitHub has refused passwords for Git operations since August 2021. And a key or dataset committed before .gitignore exists stays in the history even after you delete the file.
This guide is for data and Python learners setting up version control for the first time on Windows, macOS or Linux. Each step has the exact commands, the output to expect, and a short fix for the errors beginners hit most.
How do you install Git?
The official Git install page lists the current release for each platform.
Windows. Open the Git for Windows download page and run the installer, or install from a terminal with winget install --id Git.Git -e --source winget. The defaults are sensible. On the line-endings screen, keep "Checkout Windows-style, commit Unix-style line endings", which avoids whole-file diffs on cross-platform teams. The installer also sets up Git Credential Manager for HTTPS sign-in.
macOS. Git ships with the Xcode Command Line Tools. Running git --version prompts you to install them if they are missing, or you can install them directly:
xcode-select --install
Alternatively, use Homebrew for a newer version: brew install git.
Linux. Use your distribution's package manager:
sudo apt install git # Debian, Ubuntu
sudo dnf install git # Fedora, RHEL
How do you configure Git for the first time?
Verify the install, then set your identity and defaults:
git --version
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase false
Every commit records the name and email. Use an email address that is added to your GitHub account (or GitHub's noreply address), because according to GitHub's commit email documentation that is how commits are attributed to you.
The init.defaultBranch line matters. Without it, current Git releases still name the first branch master and print a hint that the default will change to main in Git 3.0. Meanwhile, GitHub names the default branch main in every new repository, so matching it saves a rename later. The first-time setup chapter of Pro Git notes this option needs Git 2.28 or later.
How do you authenticate with GitHub?
GitHub stopped accepting account passwords for Git operations on 13 August 2021. You have three good options.
| Method | Best for | Set-up effort | Where the secret lives |
|---|---|---|---|
| SSH key | Daily use on your own machine | Once per machine | Private key file in ~/.ssh |
| Git Credential Manager | HTTPS on Windows and macOS | Browser sign-in on first push | Operating system credential store |
| Personal access token | HTTPS where GCM is unavailable | Create in GitHub settings | Wherever you store it, so be careful |
Option 1: SSH keys
Set this up once, and there are no further password prompts. The commands follow GitHub's SSH key guide:
ssh-keygen -t ed25519 -C "you@example.com"
# press Enter for the default location; a passphrase is optional but sensible
cat ~/.ssh/id_ed25519.pub # works in macOS/Linux terminals and Git Bash on Windows
Copy the output, which is the public key. Then, in GitHub, go to Settings → SSH and GPG keys → New SSH key and paste it. Never share the file without .pub.
Test the connection:
ssh -T git@github.com
On success, GitHub replies with a message like this:
Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.
Option 2: HTTPS with Git Credential Manager or a token
If you prefer HTTPS URLs, Git Credential Manager handles sign-in through your browser and stores the result in the operating system's credential store. It is bundled with Git for Windows, so on Windows your first git push usually just opens a sign-in window.
Otherwise, create a fine-grained personal access token under Settings → Developer settings → Personal access tokens → Fine-grained tokens, then paste it when Git asks for a password. Avoid git config --global credential.helper store, because the git-credential-store documentation warns that it saves credentials unencrypted on disk.
Why write .gitignore before the first commit?
Write this before your first commit. Removing a large file from history afterwards means rewriting history, and that is a bad afternoon.
# Python
__pycache__/
*.py[cod]
.venv/
venv/
.ipynb_checkpoints/
# Data - never commit datasets
*.csv
*.parquet
*.xlsx
*.db
data/raw/
data/processed/
# Models
*.pkl
*.joblib
*.h5
# Secrets
.env
*.pem
credentials.json
config.local.yaml
# OS and editors
.DS_Store
Thumbs.db
.vscode/
.idea/
One catch: .gitignore only affects untracked files. If a file is already committed, the gitignore documentation says you must stop tracking it with git rm --cached <file> first.
Two rules are worth stating plainly.
- Never commit credentials. Automated tools scan public repositories for leaked keys, so assume anything pushed has been copied. Deleting the commit does not help, because the value is still in history. GitHub's guide to removing sensitive data says to revoke or rotate the secret first.
- Never commit large data. GitHub warns above 50 MiB and blocks files larger than 100 MiB. Keep data outside the repository and commit the script that fetches it.
How does the Git workflow work?
Git has three places a change can live: your working directory, the staging area and the repository.
git init # start a repository in this folder
git status # what has changed - use this constantly
git add script.py # stage one file
git add . # stage everything not ignored
git commit -m "Add data cleaning script"
git log --oneline --graph # history
git diff # unstaged changes
git diff --staged # staged changes
Staging exists so you can commit part of your work. For example, if you fixed a bug and renamed a variable, those can be two commits.
A worked example: .gitignore in action
Here is a new project folder containing clean.py, a secret .env file, a sales.csv dataset and a three-line .gitignore (.env, *.csv, __pycache__/). This is what git status --short shows:
?? .gitignore
?? clean.py
Neither .env nor sales.csv appears, so git add . cannot stage them. After committing, git log --oneline shows one commit (your hash will differ):
8989a17 Add data cleaning script
On Windows you may also see warning: in the working copy of 'clean.py', LF will be replaced by CRLF. That is the line-ending setting doing its job, not an error. To check why a file is ignored, run git check-ignore -v sales.csv, which prints the matching .gitignore line.
How do you connect a local repository to GitHub?
Create an empty repository on GitHub. As GitHub's guide to adding locally hosted code advises, do not initialise it with a README, licence or .gitignore if you already have local commits, which avoids an immediate conflict. Then:
git remote add origin git@github.com:username/repo.git
git remote -v # check the URL
git branch -M main # rename the current branch to main if needed
git push -u origin main
-u sets the upstream, so later pushes are just git push. For HTTPS, use https://github.com/username/repo.git as the remote URL instead.
To work with an existing repository:
git clone git@github.com:username/repo.git
cd repo
Daily rhythm:
git pull # get others' changes first
# ...work...
git add .
git commit -m "Explain what changed and why"
git push
Pull before you start, since most merge conflicts come from working on a stale copy.
How do you work on a branch in Git?
Create a branch with git switch -c <name>, commit there, then merge it back into main. That keeps main working while you experiment:
git switch -c feature/add-validation # create and switch
# ...work, commit...
git push -u origin feature/add-validation
git switch main
git merge feature/add-validation
git branch -d feature/add-validation
git switch and git restore are the modern replacements for the overloaded git checkout, which did both jobs and confused everyone.
How do you undo mistakes in Git?
Use git restore for uncommitted changes, git commit --amend or git reset --soft for commits you have not pushed, and git revert for anything already on GitHub:
git restore file.py # discard unstaged changes to a file
git restore --staged file.py # unstage, keep the changes
git commit --amend # fix the last commit message or contents
git revert <hash> # new commit undoing an old one - safe
git reset --soft HEAD~1 # undo last commit, keep changes staged
Avoid git reset --hard unless you are certain, because it discards uncommitted work irrecoverably. git revert is the safe choice for anything already pushed, since it adds a commit rather than rewriting history others may have pulled. Likewise, only --amend commits you have not pushed yet.
Git command quick reference
| Task | Command |
|---|---|
| Set identity | git config --global user.name "Your Name" |
| Start a repository | git init |
| See what changed | git status, git diff |
| Stage and commit | git add . then git commit -m "message" |
| Connect to GitHub | git remote add origin <url> |
| First push | git push -u origin main |
| Get updates | git pull |
| New branch | git switch -c <name> |
| Stop tracking a file | git rm --cached <file> |
| Undo a pushed commit | git revert <hash> |
How should you commit Jupyter notebooks?
Commit them with the outputs cleared. Notebook JSON contains execution counts and rendered outputs, which produce huge, unreadable diffs and can leak data into the repository.
Clear outputs before committing, or automate it with nbstripout:
pip install --upgrade nbstripout
nbstripout --install # installs a git filter for this repository
What makes a good commit message?
A good commit message is a short imperative summary, then a blank line, then why the change was made.
Fix revenue calculation for partial months
Prorating used calendar days rather than business days, which
understated the quarter's revenue. Switched to business-day counts
to match how finance reports the same figure.
"Update file" and "fixes" tell a future reader nothing. The why is the part that cannot be recovered from the diff.
Common mistakes beginners make with Git and GitHub
- Typing your GitHub password at the prompt. It will be rejected; use Git Credential Manager, a token or SSH.
- Creating the GitHub repository with a README, then pushing an existing project. The histories do not match, so the push is rejected.
- Adding
.gitignoreafter committing a file. The file stays tracked until you rungit rm --cached. - Ending up with both
masterandmain. A localmasterpushed to a repository whose default ismaincreates a second branch. Setinit.defaultBranch mainonce, or rename withgit branch -M mainbefore the first push. - Rewriting pushed history. Prefer
git revertoverresetand--amendon shared branches.
Git and GitHub tutorial recap: the minimum that matters
If you take five things from this Git and GitHub tutorial: configure your identity, set up SSH or Git Credential Manager, write .gitignore before the first commit, never commit secrets or data, and pull before you push.
Everything else you can look up when you need it.
The Sunday Growth Brief
One email a week: the best new comparisons, a fresh roadmap and the tech news worth your attention.
No spam. Unsubscribe in one click.
Related reading
The role of programming in data science covers reproducibility more broadly. For environment setup, see the Windows and macOS Anaconda guides. Once your project is on GitHub, a common first Python task is parsing its logs, covered in regular expressions in Python.
Frequently asked questions
What is the difference between Git and GitHub?
Git is the version control software that runs on your machine and records the history of your files. GitHub is a hosting service for Git repositories that adds collaboration features such as pull requests, issues and access control. Git works fully offline, and GitHub is only one of several places you can push to.
Why does GitHub reject my password?
GitHub stopped accepting account passwords for Git operations on 13 August 2021. Over HTTPS, sign in through Git Credential Manager, which ships with Git for Windows, or paste a personal access token when Git asks for a password. Alternatively, set up an SSH key, which avoids prompts entirely once it is configured.
I committed a large file and now cannot push. What do I do?
GitHub blocks files larger than 100 MiB. If the file is only in your most recent commit, run git rm --cached on it, add it to .gitignore, and amend the commit. If it is deeper in history, you need to rewrite history with git filter-repo, which GitHub recommends. That pain is exactly why writing .gitignore first matters.
Should I commit Jupyter notebooks?
Yes, but clear the outputs first. Notebook JSON includes execution counts and rendered output, which produces enormous, unreadable diffs and can leak data into the repository. The nbstripout tool can strip outputs automatically: install it with pip, then run nbstripout --install inside the repository to add a Git filter.
Written by
Sivaranjani S
Cloud Operations Engineer, Zoho
Cloud operations engineer and technical writer at Zoho, previously technical content consultant at 1stepGrow Academy.

