0%

Chapter 9 · practice

Habits for a Real Project

Keep Files Out of Git

A real project creates files that belong on your machine but not in its history. An environment directory can be rebuilt, a cache is generated automatically, and a local settings file may contain values that should not travel with the project. The prepared forecast project has all three kinds waiting beside useful source files.

This lesson uses dummy settings only. API_TOKEN=demo-only-not-a-secret cannot authenticate to anything. If a real credential has already entered a , removing it from the newest snapshot is not enough: the credential must be rotated, and cleaning the old history is a separate job. This chapter prevents that mistake before it happens.

See what Git is about to keep

You already use git status to see the and every outstanding path. Run it before changing anything:

git status

The report shows local.env under Changes to be committed. It is already in the , which means the index is tracking it for the next commit even though no commit contains it yet. The report also shows files under build/, __pycache__/, and .venv/ as untracked. Those are generated output, a Python cache, and a local environment. None belongs in the project history.

The committed examples/local.env is different. It is a harmless example another person can copy, so the rule for the root settings file must not hide that nested example.

Describe the files that do not belong

A file named .gitignore records project paths that Git should normally leave untracked. The file itself belongs in the , so everyone who receives the project gets the same protection. Ignore rules change what Git offers for a future commit; they do not erase a path that is already in a commit.

Open the new file with the editor from Chapter 2. nano -w opens nano without inserting hard line breaks when the terminal is narrow:

nano -w .gitignore

Enter these four lines:

/local.env
build/
__pycache__/
.venv/

The first rule is an anchored pattern. The leading / anchors local.env to the repository root, so it protects the local file without also ignoring examples/local.env.

The other rules are directory patterns. A trailing / says the name is a directory and ignores the files below it. build/ protects build output. Because __pycache__/ and .venv/ have no leading slash, a directory with either name is ignored wherever it appears in the project.

Save with Ctrl-O, press Enter to confirm .gitignore, then leave with Ctrl-X.

Run git status again. The generated directories no longer clutter the untracked list, but local.env is still staged:

git status

That result is deliberate. Ignore rules do not overrule the index. Git already has local.env queued, so you must remove the index entry while keeping the working file.

Remove the index copy and keep the file

git rm normally removes a path from both Git’s index and the working tree. The option --cached limits that removal to the index, which is Git’s prepared next snapshot. In git rm --cached local.env, the final argument names the one indexed path to stop tracking. The file on disk survives.

Run the command, then ask for status again:

git rm --cached local.env
git status

local.env disappears from the report because the file is now untracked and its ignore rule applies. Its dummy contents are still on disk.

Ask Git whether the rules match

git check-ignore tests paths against the repository’s ignore rules. Give it one or more paths after the command. It prints the paths that are ignored and prints nothing for a path that does not match.

Check each protected kind:

git check-ignore local.env build/preview.txt __pycache__/forecast.cpython-313.pyc .venv/bin/python

All four paths should be printed. The command checks behavior rather than asking you to reason from the pattern spelling. That makes it useful whenever an ignore rule is longer or less obvious than these.

Commit the protection, not the private files

git add .gitignore stages only the ignore file. The following git status is your review: it should show .gitignore ready to commit and none of the protected paths. Then git commit records that one coherent change. The -m option supplies its quoted subject without opening an editor.

git add .gitignore
git status
git commit -m "Keep local project files out of Git"
git status

The final status should report a clean working tree. The local and generated files still exist, but ignored files do not make the tree dirty. More importantly, none has entered any commit.

Match a family of filenames

Another project may need to keep every file ending in .env private, rather than only one root file. In an ignore pattern, * matches any sequence of characters within a name. The pattern *.env therefore matches local.env and testing.env; without a slash, it also matches such names inside subdirectories. It does not match environment.txt.

Keep /local.env in this exercise: its harmless examples/local.env is deliberately allowed. For the capstone’s different project, where every .env file should stay private, choose the broader *.env rule. The pattern follows the project’s needs.

Before moving on, compare settings/testing.env and settings/environment.txt. Which would *.env ignore? The first name ends in .env, so it matches; the second does not. Use git check-ignore with representative names when checking your own project’s rules.

You add a rule for a file that is already staged, but git status still lists it under changes to be committed. Why?

What does git rm --cached local.env do in this prepared repository?

You have turned a repeated cleanup decision into project behavior. The next lesson applies the other half of the habit: review one coherent change before giving its snapshot a useful subject.