Skip to content

Keep the repository clean

  • Lesson 6
  • 30 min
  • Module 2: Work with branches and remotes
Lesson 6 of 15 · Git and Team Development EssentialsKeep the repository clean

What you will be able to do

Keep passwords, keys and large generated files out of your repository. A file that you commit stays in the history, and everyone who clones the repository gets a copy.

Before you startWhat to know and to have readyAbout 30 minutes

What you need to know

What you need on your computer

  • The repository ~/projects/ticket-notes, on the branch main. git status shows working tree clean. If you are on a different branch, run git switch main.

  • The remote origin, which is the folder ~/projects/team-remote.git. You made it in Synchronize deliberately: Make a practice remote. You pushed main to it in Synchronize deliberately: Guided practice: be both people. The guided practice in this lesson pushes to it again.

  • If git remote -v shows nothing, do Make a practice remote again. Then run git push -u origin main.

  • If the repository is missing or broken, a script can make the start state of this lesson again. In ~/projects, run:

    Terminal window
    git clone https://github.com/Nextia-Intelligence/nextia-learning-labs.git
    sh nextia-learning-labs/C14/setup.sh m02-l03 --reset

    Run the git clone command only once. If you already have the nextia-learning-labs folder, run git -C nextia-learning-labs pull instead. Pull-request sequence: Set up the practice lab explains the script in full. The script makes ticket-notes, team-remote.git and sam-notes in ~/projects/c14-lab, as at the end of Synchronize deliberately: Guided practice: be both people. Sam’s commit Add ticket 102 has a different hash from the lesson (1d45995), because in the lesson you made that commit yourself. This is expected. Then use ~/projects/c14-lab in place of ~/projects in this lesson. --reset deletes an older c14-lab folder first, but your ~/projects/ticket-notes does not change.

Git keeps every version of every file that you commit. If you delete a file in a new commit, the old commits still contain it. Amira committed a settings file, then removed it in the next commit. One command still shows the old contents:

Terminal
git show c9a1952:settings.local
Output
DEBUG=true

c9a1952:settings.local means “the file settings.local as it was in commit c9a1952”. When you push, the remote gets the full history, and so does each person who clones it.

So it is much easier to keep a file out of Git than to remove it later. Three kinds of files must stay out:

Kind of file Examples Why it must stay out
Secrets .env, API keys, passwords, private keys Anyone who can read the repository can use them.
Files that tools make exports/, *.log, .venv/, node_modules/, __pycache__/ You can make them again. They change often and make diffs hard to read.
Large files datasets, trained models, .zip archives, videos Every clone downloads every version. GitHub refuses files larger than 100 MB.

A .gitignore file is a list of patterns, one on each line. Git does not show matching untracked files in git status, and git add does not stage them. You commit .gitignore itself, so the whole team uses the same rules.

Pattern Matches
.env A file or folder called .env, in any folder.
exports/ A folder called exports, and everything in it. The / at the end means “only a folder”.
*.log Every file whose name ends with .log. * means “any text”.
# text A comment. Git ignores the line.

Worked example: ignore a key, an export and a log

Section titled “Worked example: ignore a key, an export and a log”

Amira’s ticket tool needs a key, so she keeps it in a file called .env. The tool also makes exports/tickets-2026.zip and sync.log. git status --short shows all three as untracked:

git status --short
?? .env
?? exports/
?? sync.log

She makes .gitignore in the top folder of the repository:

.gitignore
# Secrets: never commit them
.env
# Files that tools make
exports/
*.log

Now git status --short shows only the new .gitignore:

git status --short
?? .gitignore

To check which rule matches a file, she uses git check-ignore -v. The output shows the file, the line number and the pattern:

Terminal
git check-ignore -v .env exports/tickets-2026.zip sync.log
Output
.gitignore:2:.env .env
.gitignore:5:exports/ exports/tickets-2026.zip
.gitignore:6:*.log sync.log

If someone tries to stage an ignored file, Git refuses:

Terminal
git add .env
Output
The following paths are ignored by one of your .gitignore files:
.env
hint: Use -f if you really want to add them.

Do not use -f for a secret. Amira commits .gitignore:

Terminal
git add .gitignore
git commit -m "Ignore secrets, exports and logs"

Worked example: a file that Git already tracks

Section titled “Worked example: a file that Git already tracks”

.gitignore affects only untracked files. If you committed a file before you added its rule, Git continues to track it.

Amira committed settings.local, then added settings.local to .gitignore and changed the file. Git still shows the change:

git status --short
M .gitignore
M settings.local

To stop tracking the file but keep it on her computer, she uses git rm --cached. --cached means “remove it from the staging area only”. Without --cached, git rm also deletes the file from the folder.

Terminal
git rm --cached settings.local
git status --short
Output
rm 'settings.local'
M .gitignore
D settings.local

D in the first column means that the next commit removes the file from the repository. She stages .gitignore too, and commits both:

Terminal
git add .gitignore
git commit -m "Stop tracking settings.local"

settings.local is still in her folder, and Git ignores it now. But the old commit c9a1952 still contains it. This is acceptable for a debug setting. For a secret, it is not: see the common mistake below.

A clean repository also has clear commits. A reviewer reads a commit to understand one change. If a commit mixes three changes, the reviewer must separate them in their head.

  • One purpose for each commit. “Add priority levels” is one purpose. “Add priority levels, fix typo, and update contacts” is three commits.
  • Check before you commit. Run git diff --staged, and read every line. Look for files that you did not mean to add.
  • Write the message as an instruction. “Add ticket 104”, not “Added stuff”. Say why in a second paragraph when the reason is not clear from the change.
  1. In ~/projects/ticket-notes, make three files that Git must not track. Use your editor, or run these commands:

    Terminal window
    echo "TICKETS_API_KEY=example-not-a-real-key" > .env
    mkdir exports
    echo "export" > exports/tickets.csv
    echo "sync started" > sync.log

    echo "text" > file writes the text into a new file.

  2. Run git status --short. All three show ??.

  3. Make .gitignore with the five lines from the worked example. Save it.

  4. Run git status --short. Only ?? .gitignore shows.

  5. Check the rules:

    Terminal window
    git check-ignore -v .env exports/tickets.csv sync.log

    Each file shows the line of .gitignore that matches it.

  6. Commit .gitignore, and push it so your team gets the same rules:

    Terminal window
    git add .gitignore
    git commit -m "Ignore secrets, exports and logs"
    git push

Your team adds Python to the ticket tool. Now the folder has these new items:

  • .venv/: a Python environment, 400 MB.
  • data/raw/tickets-full.csv: a 2 GB export of real tickets.
  • data/sample.csv: 20 made-up tickets for tests. The team wants this file in Git.
  • __pycache__/: files that Python makes.

Add rules to .gitignore so that Git ignores everything except data/sample.csv. Make the files and folders, then prove your rules with git status --short and git check-ignore -v.

Show a possible answer
.gitignore (new lines)
# Python
.venv/
__pycache__/
# Large or private data
data/raw/

git status --short then shows M .gitignore and ?? data/. data/ shows because data/sample.csv is untracked and not ignored. git check-ignore -v data/sample.csv prints nothing, which means that no rule ignores it. data/raw/ has a second reason to stay out: real tickets can contain personal data.

Common mistake

I committed a secret

Symptom: git log --stat or a review shows .env, a key or a password in a commit.

Cause: the file was staged before a .gitignore rule existed, or someone used git add -f.

Fix: act in this order.

  1. Treat the secret as public. If you pushed the commit, other people and services can have a copy. Go to the service that issued the key, and revoke it or make a new one. Do this first. It is the only step that stops misuse.
  2. Stop tracking the file with git rm --cached .env, add .env to .gitignore, and commit.
  3. Tell your team what happened and which key you replaced.

The old commit still contains the secret. Removing it from history is possible, but it rewrites shared history, and every clone must be replaced. It also does not help if someone already copied the key. That is why step 1 matters most.

Check your understanding

Amira commits config.json, which contains a password. Then she adds config.json to .gitignore and commits again. Is the password now safe?

Show the answer

No, for two reasons. First, .gitignore does not affect a file that Git already tracks, so Git still tracks config.json. She also needs git rm --cached config.json. Second, the first commit still contains the password. If she pushed it, she must change the password.

Check your understanding

Practical check: prove that .env is ignored in your repository, and show which rule does it.

Show the answer

Run git check-ignore -v .env. The output shows .gitignore, the line number and the pattern, for example .gitignore:2:.env .env. If the output is empty, no rule matches the file. Also run git status --short: .env must not appear.

Recap

  • Git keeps every committed version. Deleting a file later does not remove it from history.
  • .gitignore keeps untracked files out of git status and git add. Commit it so the whole team uses it.
  • Use git check-ignore -v to see which rule ignores a file.
  • git rm --cached stops tracking a file and keeps it in your folder.
  • If you commit a secret, replace it first. Then remove the file from tracking.
  • Make each commit one clear change, and read git diff --staged before you commit.

This is the end of Module 2. In Module 3, you put these skills together in a pull request: your team reviews your branch before it goes into main.

Next: Pull-request sequence