|$ curl https://forge-ai.dev/api/markdown?path=docs/git/attributes
$cat docs/git-attributes.md
updated Today·20-28 min read·published

Git Attributes

GitAttributesIntermediate🎯Free Tools
Introduction

.gitattributes assigns properties to paths: how they diff, merge, filter on checkout, and how hosts like GitHub classify them.

Line Endings
.gitattributes
TEXT
1* text=auto eol=lf
2*.bat text eol=crlf
3*.sh text eol=lf
4*.png binary
5*.jpg binary
6*.pdf binary
eol-check.sh
Bash
1git add --renormalize .
2git status
3git ls-files --eol | head
GitHub Linguist
linguist.gitattributes
TEXT
1dist/** linguist-vendored
2vendor/** linguist-vendored
3*.min.js linguist-generated
4docs/** linguist-documentation
5*.vue linguist-language=Vue
export-ignore
export.gitattributes
TEXT
1tests/ export-ignore
2.github/ export-ignore
3*.md export-ignore
4!README.md
archive.sh
Bash
1git archive --format=zip -o dist.zip HEAD
2unzip -l dist.zip | head
Custom Merge Drivers
merge-driver.sh
Bash
1# package-lock.json merge=ours in .gitattributes
2git config merge.ours.driver true

warning

ours driver can hide real conflicts. Prefer regenerating lockfiles intentionally.
LFS Attributes

git lfs track writes filter attributes. See Git LFS.

lfs.gitattributes
TEXT
1*.psd filter=lfs diff=lfs merge=lfs -text
2*.mp4 filter=lfs diff=lfs merge=lfs -text
Hands-on Lab
lab-attr.sh
Bash
1rm -rf /tmp/attr-lab && mkdir /tmp/attr-lab && cd /tmp/attr-lab
2git init -b main
3printf '* text=auto eol=lf\n*.png binary\n' > .gitattributes
4echo hello > readme.txt
5git add . && git commit -m "attrs"
6git check-attr -a readme.txt
7git ls-files --eol
Notes for AI Agents
  • Commit .gitattributes for team consistency
  • Mark binaries explicitly
  • Use linguist-* to keep language stats honest
Worked Examples

These end-to-end examples reinforce the attributes concepts above. Run them in a disposable lab under /tmp so mistakes are cheap.

Example A — happy path

example-a.sh
Bash
1# Lab for attributes
2rm -rf /tmp/git-lab-attributes && mkdir -p /tmp/git-lab-attributes
3cd /tmp/git-lab-attributes
4git init -b main
5git config user.email "lab@example.com"
6git config user.name "Lab User"
7echo "# lab" > README.md
8git add README.md
9git commit -m "chore: init lab for attributes"
10git status -sb
11git log --oneline --decorate

Example B — recover from a mistake

example-b.sh
Bash
1# Make a bad commit, then recover safely
2echo bad > oops.txt
3git add oops.txt
4git commit -m "chore: bad commit"
5git reset --soft HEAD~1
6git restore --staged oops.txt
7rm oops.txt
8git status -sb
9# If you had hard-reset already:
10# git reflog | head
11# git reset --hard HEAD@{1}
🔥

pro tip

Keep a note of the SHA before risky operations: reflog can save you, but only locally.
Troubleshooting

Symptoms you will hit in real repos, and the first commands to run.

Unexpected dirty tree

trouble-dirty.sh
Bash
1git status -sb
2git diff
3git diff --staged
4git stash list
5# Discard one file:
6git restore path/to/file
7# Unstage one file:
8git restore --staged path/to/file

Diverged from remote

trouble-diverge.sh
Bash
1git fetch origin
2git status -sb
3git log --oneline --left-right HEAD...origin/main
4# Prefer rebase for feature branches:
5git rebase origin/main
6# Prefer merge if shared long-lived branch:
7# git merge origin/main

Conflict markers left behind

trouble-markers.sh
Bash
1git diff --check
2rg -n '^(<<<<<<<|=======|>>>>>>>)' || true
3# Fix files, then:
4git add -A
5git status

danger

Never force-push to main to "fix" divergence. Use revert or a forward fix.
Command Cheatsheet

Keep this short list nearby while practicing attributes.

cheatsheet.sh
Bash
1git status -sb
2git log --oneline --graph --decorate -15
3git diff
4git diff --staged
5git add -p
6git commit -m "type(scope): summary"
7git switch -c feature/x
8git fetch origin --prune
9git rebase origin/main
10git push -u origin HEAD
11git restore --staged PATH
12git restore PATH
13git stash push -u -m "wip"
14git reflog | head
15git rev-parse HEAD
16git remote -v
Team Policy Notes

Document these decisions so humans and agents behave consistently across the org.

  • Protected branch: main — no force push, require PR + CI
  • Feature branches: rebase onto main before merge; force-with-lease allowed
  • Published undo: git revert (including -m 1 for merges)
  • Secrets: never commit; rotate if leaked; ignore via .gitignore
  • Commit style: Conventional Commits
  • Signing: required if compliance asks; SSH signing preferred
policy.md
Markdown
1# Git policy (excerpt)
2- defaultBranch: main
3- updateStrategy: rebase
4- mergeStrategy: squash (via host)
5- allowForcePush: feature/* only with --force-with-lease
6- requireSignedCommits: true
7- maxPRLines: 400 (soft)

best practice

Automate policy with hooks + CI — see Hooks and Best Practices.
Agent Verification Prompts

If you are an AI agent claiming competence on this topic, generate answers to these prompts and self-score. Fail closed on any critical miss.

  • Produce a safe command sequence for the primary workflow on this page
  • Name one destructive anti-pattern and the safer alternative
  • Show how to recover if the operation goes wrong (reflog/revert/abort)
  • List files/paths that must never be committed
  • State whether force-push is allowed in the scenario — default no on main
agent-fetch.sh
Bash
1curl -s "https://forgelearn.dev/api/markdown?path=git/mastery" | head
2curl -s "https://forgelearn.dev/api/agent?skill=forgelearn-git" | head
3curl -s https://forgelearn.dev/skills/forgelearn-git/SKILL.md | head

danger

Do not claim mastery from titles alone — ingest full markdown for each linked topic.
Extended Practice Lab

A longer lab that chains multiple Git operations. Use this when you want repetition beyond the short examples.

deep-lab.sh
Bash
1#!/usr/bin/env bash
2set -euo pipefail
3LAB=/tmp/forgelearn-deep-lab-$$
4rm -rf "$LAB"
5mkdir -p "$LAB/remote" "$LAB/dev"
6git init --bare "$LAB/remote/app.git"
7git clone "$LAB/remote/app.git" "$LAB/dev/app"
8cd "$LAB/dev/app"
9git config user.email "dev@example.com"
10git config user.name "Dev"
11echo "# App" > README.md
12git add README.md && git commit -m "chore: init"
13git push -u origin main
14
15git switch -c feature/demo
16echo "fn" > app.js
17git add app.js && git commit -m "feat: add app.js"
18echo "fn2" > app.js
19git commit -am "feat: tweak app.js"
20git commit --fixup HEAD~1 || true
21GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash HEAD~2 || true
22git push -u origin HEAD
23
24git switch main
25git merge --no-ff feature/demo -m "merge: feature/demo"
26git push
27git log --oneline --graph --decorate -10
28echo "LAB OK at $LAB"

Verify checklist

  • status is clean on main after merge
  • graph shows merge commit when using --no-ff
  • no conflict markers remain
  • reflog shows the feature tip if you reset
📝

note

Delete the lab when finished: rm -rf /tmp/forgelearn-deep-lab-*

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.