Git & GitHub

Tracking Changes

13 min Lesson 5 of 35

Tracking Changes

Now that you know the basic Git workflow, let's dive deeper into tracking changes. In this lesson, you'll learn how to use git status effectively, understand different ways to stage files, move and remove files, and control which files Git ignores.

Understanding git status Output

The git status command is your best friend in Git. It shows you exactly what's happening in your repository:

# Check repository status git status Typical Output: On branch main Your branch is up to date with 'origin/main'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: index.html modified: style.css Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: script.js Untracked files: (use "git add <file>..." to include in what will be committed) config.json

Breaking Down the Output

1. Branch Information: "On branch main" - You're currently on the main branch "Your branch is up to date" - Your local branch matches remote 2. Changes to be committed (Staged): Files that are staged and ready for commit • new file: Brand new file added to Git • modified: Existing file that was changed and staged 3. Changes not staged for commit (Modified): Files that Git tracks but have unstaged changes You've modified them but haven't run git add yet 4. Untracked files: Files Git sees but isn't tracking New files that have never been added

Compact Status Output

# Short status format git status -s git status --short Output: M style.css # Staged modification M script.js # Unstaged modification A index.html # Staged new file ?? config.json # Untracked file MM README.md # Modified, staged, then modified again Status Codes: ?? = Untracked A = Added (staged new file) M = Modified D = Deleted R = Renamed C = Copied MM = Modified in staging and working directory
Pro Tip: Use git status -s for a quick overview, and git status for detailed information with helpful hints.

Different Ways to Stage Files

1. Stage Specific Files

# Stage one file git add filename.txt # Stage multiple specific files git add file1.txt file2.css file3.js # Stage files with pattern git add *.html # All HTML files in current directory git add src/*.js # All JS files in src directory git add **/*.css # All CSS files recursively

2. Stage All Changes

# Stage all changes in current directory and subdirectories git add . # Stage all changes in entire repository (recommended) git add -A git add --all # Stage only modified and deleted files (not new files) git add -u git add --update
Difference between git add . and git add -A: git add . • Stages everything in current directory and subdirectories • Relative to your current location git add -A • Stages everything in entire repository • Works from any directory • More predictable and safer Recommendation: Use git add -A for consistency

3. Interactive Staging (git add -p)

Stage parts of files rather than entire files:

# Interactive patch mode git add -p filename.txt git add --patch What happens: Git shows each change (hunk) and asks what to do: Stage this hunk [y,n,q,a,d,s,e,?]? y - Yes, stage this hunk n - No, don't stage this hunk q - Quit, don't stage this or remaining hunks a - Stage this and all remaining hunks d - Don't stage this or remaining hunks s - Split this hunk into smaller hunks e - Manually edit this hunk ? - Show help
Example Scenario: You have one file with two separate bug fixes: 1. Fix for login validation 2. Fix for password reset Using git add -p: • Stage fix #1: y • Don't stage fix #2: n Result: You can commit fix #1 separately! This keeps your commits atomic and logical.
Use Case: Interactive staging is perfect when you've made multiple unrelated changes to the same file and want to commit them separately.

4. Interactive Mode (git add -i)

# Full interactive mode git add -i git add --interactive Provides a menu: *** Commands *** 1: status 2: update 3: revert 4: add untracked 5: patch 6: diff 7: quit 8: help Allows you to: • See status • Stage files interactively • Unstage files • Add untracked files • View diffs

Moving and Renaming Files

# Rename a file git mv old-name.txt new-name.txt # Move a file to different directory git mv file.txt src/file.txt # Rename and move in one command git mv old-name.txt src/new-name.txt What git mv does: 1. Renames/moves the file in working directory 2. Stages the deletion of old file 3. Stages the addition of new file 4. Git recognizes it as a rename (not delete + add)
Why use git mv instead of regular mv? Regular way (manual): mv old.txt new.txt git rm old.txt git add new.txt Git way (automatic): git mv old.txt new.txt Benefits: ✓ One command instead of three ✓ Git preserves file history ✓ Cleaner commit history

Removing Files

# Remove file from Git and working directory git rm filename.txt # Remove file from Git but keep in working directory git rm --cached filename.txt # Remove multiple files git rm *.log # Remove directory git rm -r directory-name/ # Force removal (if file has changes) git rm -f filename.txt
When to use git rm vs rm: Regular rm: rm file.txt # Only removes from disk git add file.txt # Must manually stage deletion Git rm: git rm file.txt # Removes and stages in one step Common Use Cases: # Accidentally committed sensitive file git rm --cached .env # Remove from Git, keep locally # Remove all log files git rm *.log # Remove completely # Remove file but keep local copy git rm --cached temp.txt # Keep for local development
Important: git rm --cached removes the file from Git but keeps it in your working directory. This is useful for files you want to keep locally but not track in Git (like configuration files).

Ignoring Files with .gitignore

Not all files should be tracked by Git. The .gitignore file tells Git which files to ignore:

Creating .gitignore

# Create .gitignore file touch .gitignore # Edit with your preferred editor nano .gitignore # Add to Git git add .gitignore git commit -m "Add .gitignore"

Common .gitignore Patterns

# Example .gitignore file # Dependencies node_modules/ vendor/ # Environment files .env .env.local .env.*.local # Logs *.log logs/ npm-debug.log* # Operating System files .DS_Store # macOS Thumbs.db # Windows *.swp # Vim # IDE files .vscode/ .idea/ *.sublime-project # Build output dist/ build/ *.min.js *.min.css # Temporary files *.tmp *.temp tmp/ # Database files *.sqlite *.db # Compiled files *.class # Java *.pyc # Python *.o # C/C++ # Specific file config/secret.json # All files in directory cache/* # All .txt files in root only /*.txt # Exception: Don't ignore this file !important.txt

.gitignore Pattern Rules

Pattern Matching: *.log # Ignore all .log files build/ # Ignore entire build directory temp # Ignore temp file or directory /TODO.txt # Ignore only in root directory doc/**/*.pdf # Ignore PDFs anywhere under doc/ Negation (Exceptions): *.log # Ignore all log files !important.log # But track important.log Comments: # This is a comment # Use # at the start of line Blank Lines: Blank lines are ignored (use for organization)
Best Practice: Create .gitignore at the start of your project. It's much easier than removing files later that were accidentally tracked.

What Should You Ignore?

Always Ignore: ✓ Dependencies (node_modules/, vendor/) ✓ Build output (dist/, build/) ✓ Environment variables (.env) ✓ API keys and secrets ✓ Passwords and credentials ✓ Operating system files (.DS_Store) ✓ IDE configuration (.vscode/, .idea/) ✓ Log files (*.log) ✓ Temporary files (*.tmp) ✓ Database files (*.sqlite) Never Ignore: ✗ Source code ✗ Documentation ✗ Configuration templates (.env.example) ✗ Tests ✗ README files

Global .gitignore

# Set up global .gitignore for all repositories git config --global core.excludesfile ~/.gitignore_global # Create the file touch ~/.gitignore_global # Add common patterns echo ".DS_Store" >> ~/.gitignore_global echo "*.swp" >> ~/.gitignore_global echo ".vscode/" >> ~/.gitignore_global Use Case: Put personal preferences here (IDE, OS files) Keep project-specific ignores in project .gitignore

Checking Ignored Files

# See which files are ignored git status --ignored # Check if specific file is ignored git check-ignore -v filename.txt Output shows: .gitignore:3:*.txt filename.txt (file, line number, pattern, filename) # List all ignored files git ls-files --others --ignored --exclude-standard

Untracking Already-Tracked Files

Problem: You added a file to .gitignore, but Git still tracks it (because it was committed before .gitignore was created) Solution: # Remove from Git but keep locally git rm --cached filename.txt # Remove directory from Git but keep locally git rm -r --cached directory/ # Remove everything and re-add (nuclear option) git rm -r --cached . git add . # Commit the changes git commit -m "Remove ignored files from tracking" Result: File is no longer tracked but remains on your disk
Important: If a file was previously committed and pushed, it's in Git history. Even after removing it, others can still see it in old commits. Use tools like git-filter-repo to completely remove sensitive data from history.

Template .gitignore Files

GitHub provides templates for different languages/frameworks: Visit: https://github.com/github/gitignore Templates available: • Node.js • Python • Java • Ruby • PHP • Laravel • React • And 100+ more Using a template: 1. Visit the repository 2. Find your language/framework 3. Copy the .gitignore content 4. Paste into your .gitignore file Or use GitHub when creating repository: • Select "Add .gitignore" dropdown • Choose your language

Practical Example: Complete Workflow

# Start new project mkdir my-app && cd my-app git init # Create .gitignore first cat > .gitignore << EOF node_modules/ .env *.log dist/ EOF # Create project files echo "console.log('Hello');" > app.js echo "API_KEY=secret123" > .env mkdir dist # Check status git status Output: Untracked files: .gitignore app.js (Notice .env is NOT shown - it's ignored!) # Stage and commit git add . git commit -m "Initial commit with source code" # Create log file (will be ignored) echo "Error log" > error.log # Check status git status Output: nothing to commit, working tree clean (error.log is ignored) # Verify ignored files git status --ignored Output shows error.log is ignored

Hands-On Exercise:

Practice tracking and ignoring files:

  1. Create a new Git repository
  2. Create a .gitignore that ignores *.log and temp/
  3. Create: index.html, style.css, debug.log, temp/cache.txt
  4. Run git status and verify .log and temp/ are ignored
  5. Stage only index.html
  6. Check status with git status -s
  7. Stage remaining tracked files
  8. Commit all changes

Commands:

mkdir test-repo && cd test-repo
git init
echo -e "*.log\ntemp/" > .gitignore
touch index.html style.css debug.log
mkdir temp && touch temp/cache.txt
git status
git add index.html
git status -s
git add .
git commit -m "Add website files"

Summary

In this lesson, you learned:

  • How to read and interpret git status output in detail
  • Different ways to stage files: specific, all, patterns, interactive
  • How to use git add -p for staging parts of files
  • Moving and renaming files with git mv
  • Removing files with git rm and git rm --cached
  • Creating and using .gitignore files
  • Common .gitignore patterns and best practices
  • How to check which files are ignored
  • Untracking previously tracked files
  • Using .gitignore templates for different projects
Next Up: In the next lesson, we'll learn about making commits, writing professional commit messages, and amending commits when you make mistakes!

ES
Edrees Salih
11 hours ago

We are still cooking the magic in the way!