Repositories, Working Tree, Index, HEAD, and the File Lifecycle: Configuration, Design Choices, and Tradeoffs
Design portable tracking and ignore policy across repository, local, and global scopes; reason about pathspecs, shell expansion, file modes, case sensitivity, partial staging, intent-to-add, generated files, dependencies, and secrets.
Learning objectives
- Choose the correct ignore source for shared, repository-local, and user-global exclusions.
- Separate Git pathspec matching from shell wildcard expansion and use -- to disambiguate paths.
- Reason about file-mode and case-sensitivity behavior without copying machine-specific settings blindly.
- Evaluate partial staging and intent-to-add as deliberate advanced workflows.
- Define tracking policy for generated artifacts, caches, dependencies, and secrets.
1. File lifecycle becomes a team policy problem
The mechanics from Lesson 2 answer “how do I stage or restore this path?” Production repositories also need a policy for which paths should exist in history at all, which excludes are shared, which are private, and how cross-platform filesystems affect path identity.
2. Ignore sources and precedence
Git's current ignore precedence, highest to lowest, is:
- patterns supplied on the command line by commands that support them;
-
.gitignorefiles from the path's directory upward to the working-tree root, with deeper files able to override higher ones; -
$GIT_COMMON_DIR/info/excludefor repository-specific but unshared ignores; -
the file configured by
core.excludesFilefor user-wide personal patterns.
| Need | Best home | Why |
|---|---|---|
| Build output every contributor should ignore | Versioned .gitignore |
Shared project policy |
| One developer's local scratch directory | .git/info/exclude |
Repository-local, not shared |
| Editor backup files across all repos | core.excludesFile |
User preference |
| Already tracked secret/config | Not solved by ignore alone | Tracking/history/security action required |
3. Ignore rules do not untrack existing files
If a file is already in the index, adding a matching ignore rule does not silently remove it from history. This is a safety property: a new ignore pattern should not unexpectedly delete versioned content.
git ls-files -- config.local
git check-ignore -v --no-index -- config.local
If the project deliberately wants to keep a local copy but stop
tracking future versions, git rm --cached -- path can
change the index while preserving the working-tree file. That
decision should be reviewed, especially if the path ever contained
credentials: ignoring it does not erase prior commits or revoke
exposed secrets.
4. Git pathspecs versus shell wildcard expansion
These two commands can behave differently:
git add src/*.py
git add -- "src/*.py"
In shells that expand globs, the first form may be converted into a concrete list of files before Git starts. The quoted second form lets Git receive and interpret the pathspec. PowerShell wildcard behavior differs from Bash/zsh, so portable documentation should quote Git pathspec patterns when Git—not the shell—is intended to perform matching.
5. Separate revisions from paths with --
Git commands such as diff can accept both revision
expressions and paths. If a branch/tag and path share the same name,
ambiguity becomes operationally dangerous.
git diff HEAD -- release
git show HEAD:release
git status -- release
Teach scripts and runbooks to use -- whenever the
command grammar accepts both revisions/options and paths. A path
beginning with - is another reason to make the boundary
explicit.
6. File-mode differences across filesystems
Git tracks a limited executable-bit concept in tree entries.
core.fileMode tells Git whether to honor working-tree
executable-bit changes. Git normally probes this during repository
creation/clone, but copied repositories, network mounts, containers,
or Windows interoperability layers can alter behavior.
git config --show-origin --get core.fileMode
git diff --summary
Do not set one global value for every machine merely to silence a symptom. Decide whether executable-bit changes are meaningful for the project and whether the filesystem can represent them reliably.
7. Case sensitivity is a filesystem boundary, not just style
Git relies on core.ignoreCase workarounds on
case-insensitive filesystems. Paths such as
Makefile and makefile can coexist on a
case-sensitive filesystem but cause ambiguity on common
Windows/macOS setups. A portable repository should avoid case-only
path distinctions even if one contributor's filesystem permits them.
For case-only renames on case-insensitive filesystems, an intermediate name is often clearer:
git mv Readme.md readme.tmp
git mv readme.tmp README.md
git status --short
8. Partial staging — powerful, but it changes review assumptions
git add -p lets the index contain only selected hunks
from a working-tree file. This supports focused commits, but it
means “the file on disk” is no longer “the file being committed.”
Teams that use partial staging should require a final
git diff --staged review and ideally run tests against
the exact staged snapshot when correctness depends on the split.
9. Intent-to-add is an advanced visibility choice
git add -N -- new-file.txt
git status --short
git diff -- new-file.txt
--intent-to-add records an index entry indicating that
the path is intended to be added later while allowing the
working-tree content to participate in diff workflows. It is useful
in some review/partial-staging workflows, but beginners should not
treat it as ordinary staging: the file's content still needs to be
added before a normal commit records it.
10. Generated files, caches, dependencies, and secrets need different reasoning
| Path category | Default reasoning | Exceptions |
|---|---|---|
| Build output / caches | Usually ignore | Checked-in generated artifacts when reproducibility/release policy explicitly requires them |
| Vendored dependencies | Prefer package lockfiles + package manager | Air-gapped/reproducible vendor policy may justify tracking |
| Generated docs/API clients | Team decision | Track when consumers need artifacts without generator toolchain |
| Secrets/private keys/tokens | Never track as ordinary source | Use secret-management references/templates, not live credentials |
| Local IDE/editor files | User/global or repo-local excludes | Track shared workspace config only when intentionally standardized |
11. Ignoring a secret is prevention, not incident response
12. Worked policy scenario
A cross-platform service repository contains Python bytecode caches,
a generated dist/ directory, a developer-only
.notes/ folder, a tracked shell deployment script, and
an .env file containing real credentials.
-
Version
__pycache__/anddist/patterns in project.gitignoreunless distribution artifacts are intentionally versioned. -
Put
.notes/in.git/info/excludeif only one developer needs it. -
Preserve executable-bit intent for the deployment script on
capable filesystems; avoid global
core.fileModecargo-culting. -
Ignore
.envbefore it is ever committed; ship a safe.env.exampletemplate. - If real credentials were already committed, rotate first and follow the later history-remediation process.
13. Knowledge check
Question 1. Where should a team-wide generated
dist/ ignore normally live?
.gitignore, because the
rule is shared project policy.
Question 2. Why quote "src/*.py" in a Git
command?
Question 3. Is git add -N equivalent to staging
the file's full contents?
Question 4. A secret is already committed. Is adding it to
.gitignore sufficient?
14. Summary
Tracking policy has three owners: the project, the repository-local user, and the global user environment. Pathspecs are Git syntax, shell expansion is a separate boundary, filesystem case/mode behavior is machine-sensitive, and advanced index workflows such as partial staging or intent-to-add require deliberate review discipline.
Authoritative references
gitignore
git-check-ignore
Git pathspec glossary
git-add
git-config
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.