Skip to content

gitignore and gitattributes

Overview

Without .gitignore, engineers commit .terraform/ directories, node_modules/, and .env files containing secrets — triggering security incidents and bloated repositories. Without .gitattributes, Windows and Linux developers fight line-ending wars in YAML and shell scripts. These two files are infrastructure-as-code hygiene essentials.

This is Tutorial 12 in Module 4: Collaboration of the REBASH Academy Git series.

Prerequisites

Learning Objectives

By the end of this tutorial, you will be able to:

  • Write .gitignore patterns for common DevOps stacks
  • Understand gitignore precedence and negation rules
  • Remove accidentally tracked files from Git history scope
  • Configure .gitattributes for line endings and diff behavior
  • Mark binary files and generated files appropriately
  • Use global gitignore for personal editor files
  • Apply linguist and export-ignore attributes for GitHub

Ignore Flow Diagram

flowchart TB
    FILES[Working Directory Files]
    GI[.gitignore patterns]
    GA[.gitattributes rules]
    STAGE["git add / staging"]
    REPO[Repository]

    FILES --> GI
    GI -->|excluded| SKIP[Not tracked]
    GI -->|allowed| STAGE
    GA --> STAGE
    STAGE --> REPO```

## Theory

### .gitignore Purpose

Gitignore tells Git which files to **ignore** — never stage or commit unless forced with `git add -f`.

Patterns apply to:

- Untracked files (primary use)
- Already tracked files are NOT ignored until removed from index

### Pattern Syntax

| Pattern | Matches |
|---------|---------|
| `*.log` | Any `.log` file in any directory |
| `/build/` | `build/` at repo root only |
| `**/tmp/` | `tmp/` anywhere |
| `!important.log` | Negation — do track this file |
| `config/**` | Everything under config/ |

Later rules override earlier; negation un-ignores specific paths.

### DevOps gitignore Essentials

**Terraform:**

```gitignore
.terraform/
*.tfstate
*.tfstate.*
.terraform.lock.hcl
# Note: some teams commit .terraform.lock.hcl — document policy
crash.log
override.tf
*.tfvars
!example.tfvars

Python:

__pycache__/
*.py[cod]
.venv/
.env

Kubernetes / general:

*.pem
*.key
secrets/
.env.local

Use templates from gitignore.io or GitHub's gitignore repository.

Global gitignore

Personal editor files shouldn't be in project gitignore:

git config --global core.excludesfile ~/.gitignore_global
# ~/.gitignore_global
.DS_Store
.idea/
*.swp
.vscode/

Removing Tracked Files That Should Be Ignored

git rm --cached secrets.env
git commit -m "chore: stop tracking secrets.env"
echo "secrets.env" >> .gitignore

--cached removes from index only — keeps local file.

.gitattributes Purpose

Controls how Git handles files:

  • Line ending normalization (text, eol=lf)
  • Diff driver (how diffs display)
  • Merge strategy for specific files
  • Linguist language detection (GitHub)
  • Export-ignore for archive

Line Endings

* text=auto
*.sh text eol=lf
*.bat text eol=crlf
*.png binary

* text=auto lets Git normalize line endings on checkout/commit — critical for cross-platform teams editing YAML and shell scripts.

Custom Diff Drivers

*.tf diff=terraform

Requires config:

git config diff.terraform.xfuncmd "terraform fmt -check"

Merge Strategies for Lock Files

package-lock.json merge=ours

Controversial — many teams regenerate lock files post-merge instead.

export-ignore

Exclude CI artifacts from git archive:

.github/ export-ignore
tests/ export-ignore

Hands-on Lab

Step 1 – Create repo and demonstrate ignore

Command:

mkdir -p /tmp/gitignore-lab && cd /tmp/gitignore-lab
git init -b main
cat > .gitignore << 'EOF'
*.log
.terraform/
.env
!example.env
EOF
echo "secret=1" > .env
echo "secret=example" > example.env
echo "debug" > app.log
mkdir .terraform && echo "state" > .terraform/plugin
git status

Explanation: .env and .log ignored; example.env tracked via negation.

Step 2 – Commit allowed files

Command:

git add .
git status
git commit -m "chore: add gitignore and example env"
git check-ignore -v app.log .env example.env

Step 3 – Add gitattributes

Command:

cat > .gitattributes << 'EOF'
* text=auto eol=lf
*.sh text eol=lf
*.png binary
*.md diff=markdown
EOF
echo '#!/bin/sh' > deploy.sh
echo 'echo deploy' >> deploy.sh
git add .gitattributes deploy.sh && git commit -m "chore: add gitattributes"

Step 4 – Remove accidentally tracked file

Command:

echo "oops" > .env
git add -f .env && git commit -m "mistake: tracked secret"
git rm --cached .env
git commit -m "chore: untrack .env"
git status
test ! -f .env && echo "file missing" || echo ".env still on disk"

Step 5 – Verify attributes

Command:

git check-attr -a deploy.sh
git check-attr binary -- *.png 2>/dev/null || echo "no png files"

Step 6 – Clean up

Command:

cd /tmp && rm -rf gitignore-lab

Commands & Code

Command Description Example
git check-ignore -v file Why file is ignored git check-ignore -v .env
git rm --cached file Untrack without deleting git rm --cached secrets.env
git add -f file Force add ignored file Rare — usually wrong
git check-attr -a file Show attributes git check-attr -a deploy.sh
git config core.excludesfile Global ignore path Set global gitignore

Terraform starter .gitignore

# Local .terraform directories
.terraform/

# .tfstate files contain sensitive data
*.tfstate
*.tfstate.*

# Variable files with secrets
*.tfvars
*.tfvars.json
!terraform.tfvars.example

# CLI config
.terraformrc
terraform.rc

# Crash logs
crash.log
crash.*.log

Common Mistakes

Committing .terraform.lock.hcl without team policy

Hashicorp recommends committing lock file for provider consistency. Document whether your org commits it.

gitignore does not untrack existing files

Must git rm --cached after adding pattern for already-tracked files.

Overly broad ignore patterns

*.yaml ignoring all YAML breaks K8s manifests. Be specific.

Missing binary attribute on images

Git may corrupt binary files with line-ending conversion. Mark binary.

Best Practices

Commit example env files

example.env or terraform.tfvars.example with dummy values — never real secrets.

Scan repos for secrets in CI

gitignore is not foolproof. Use gitleaks or trufflehog in pipelines.

Standardize gitattributes org-wide

Platform team maintains template copied into new repos.

Review gitignore in every new repo PR

First commit should include stack-appropriate ignore rules.

Troubleshooting

Issue Cause Solution
File still tracked after gitignore Already in index git rm --cached
Negation not working Order wrong Put ! pattern after ignore
CRLF in Linux CI Missing gitattributes Add * text=auto eol=lf
Huge repo size Committed artifacts BFG/filter-repo; fix gitignore
check-ignore shows nothing File not ignored Verify pattern syntax
Wrong diff for generated file Missing -diff attribute generated.xml -diff

Summary

  • .gitignore excludes files from tracking — essential for secrets, build output, and local state
  • Negation patterns (!) re-include specific files under broad rules
  • git rm --cached stops tracking without deleting local files
  • .gitattributes controls line endings, binary handling, and diff/merge behavior
  • DevOps repos need stack-specific patterns for Terraform, Python, Node, and secrets

Interview Questions

  1. What is the purpose of .gitignore?
  2. How do you stop tracking a file without deleting it locally?
  3. What does the negation pattern !important.log do?
  4. Why doesn't gitignore affect already-tracked files?
  5. What is .gitattributes used for?
  6. What should a Terraform .gitignore include?
  7. What does * text=auto eol=lf accomplish?
  8. What is a global gitignore, and when use it?
  9. Why mark files as binary in gitattributes?
  10. How would you prevent secrets.env from ever being committed again?
Sample Answers (Questions 2 and 6)

Q2 — Untrack without delete: Run git rm --cached filename to remove from index while keeping the working tree file. Commit the change. Add filename to .gitignore so it won't be re-added. Local file remains for developer use.

Q6 — Terraform gitignore: Exclude .terraform/ provider cache, *.tfstate and backups (contain secrets), local *.tfvars with credentials, override files, crash logs. Optionally include .terraform.lock.hcl per team policy. Include !example.tfvars for documentation templates.

References