# Git and GitHub Tutorial: Install Git and Push to a Remote Repository

> A Git and GitHub tutorial for beginners: install Git, sign in with SSH or a token (GitHub rejects passwords), write .gitignore, push, and undo mistakes.

- **Author:** Sivaranjani S — Cloud Operations Engineer, Zoho (https://www.1stepgrow.com/authors/sivaranjani-s/)
- **Published:** Jul 10, 2026 · **Updated:** Sep 17, 2026
- **Topic:** Python & Programming · **Format:** Guide · **Read time:** 10 min
- **Canonical URL:** https://www.1stepgrow.com/articles/git-and-github-tutorial/

## Key takeaways

- GitHub stopped accepting account passwords for Git operations on 13 August 2021, so use SSH keys, Git Credential Manager or a personal access token.
- Write .gitignore before your first commit, because removing a large file from history afterwards means rewriting history.
- Never commit credentials; if one is pushed, revoke or rotate it first, because deleting the commit does not make it safe.
- Git still names the first branch master unless you configure init.defaultBranch, while GitHub names new repositories' default branch main.
- Commit messages that explain why beat messages that only describe what changed.

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](https://git-scm.com/install/) lists the current release for each platform.

**Windows.** Open the [Git for Windows download page](https://git-scm.com/install/windows) 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:

```bash
xcode-select --install
```

Alternatively, use Homebrew for a newer version: `brew install git`.

**Linux.** Use your distribution's package manager:

```bash
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:

```bash
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](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-email-preferences/setting-your-commit-email-address) 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`](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches) in every new repository, so matching it saves a rename later. The [first-time setup chapter of Pro Git](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) 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](https://github.blog/security/application-security/token-authentication-requirements-for-git-operations/). 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](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent):

```bash
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:

```bash
ssh -T git@github.com
```

On success, GitHub replies with a message like this:

```text
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](https://docs.github.com/en/get-started/git-basics/caching-your-github-credentials-in-git) 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](https://git-scm.com/docs/git-credential-store) 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.

```gitignore
# 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](https://git-scm.com/docs/gitignore) 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](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository) says to revoke or rotate the secret first.
- **Never commit large data.** [GitHub warns above 50 MiB and blocks files larger than 100 MiB](https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-large-files-on-github). 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**.

```bash
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:

```text
?? .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):

```text
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](https://docs.github.com/en/migrations/importing-source-code/using-the-command-line-to-import-source-code/adding-locally-hosted-code-to-github) advises, do **not** initialise it with a README, licence or `.gitignore` if you already have local commits, which avoids an immediate conflict. Then:

```bash
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:

```bash
git clone git@github.com:username/repo.git
cd repo
```

Daily rhythm:

```bash
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:

```bash
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:

```bash
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](https://github.com/kynan/nbstripout):

```bash
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.

```text
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 `.gitignore` after committing a file.** The file stays tracked until you run `git rm --cached`.
- **Ending up with both `master` and `main`.** A local `master` pushed to a repository whose default is `main` creates a second branch. Set `init.defaultBranch main` once, or rename with `git branch -M main` before the first push.
- **Rewriting pushed history.** Prefer `git revert` over `reset` and `--amend` on 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.



## Related reading

[The role of programming in data science](https://www.1stepgrow.com/articles/programming-for-data-science) covers reproducibility more broadly. For environment setup, see the [Windows](https://www.1stepgrow.com/articles/install-anaconda-windows) and [macOS](https://www.1stepgrow.com/articles/install-anaconda-mac) Anaconda guides. Once your project is on GitHub, a common first Python task is parsing its logs, covered in [regular expressions in Python](https://www.1stepgrow.com/articles/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.

---
_Source: 1stepGrow (https://www.1stepgrow.com/articles/git-and-github-tutorial/). Cite with the title, "1stepGrow" and a link._
