Chapters

Hide chapters

Git Apprentice

First Edition · Git 2.28 · Console

Section I: Beginning Git

Section 1: 11 chapters
Show chapters Hide chapters

4. The Staging Area
Written by Chris Belanger

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In previous chapters, you’ve gained some knowledge of the staging area of Git: You’ve learned how to stage modifications to your files, stage the addition of new files to the repository, view diffs between your working tree and the staging area, and you even got a little taste of how git log works.

But there’s more to the staging area than just those few operations. At this point, you may be wondering why the staging area is necessary. “Why can’t you just push all of your current updates to the repository directly?”, you may ask. It’s a good question, but there are issues with that linear approach; Git was actually designed to solve some of the common issues with direct-commit history that exist under other version control systems.

In this chapter, you’ll learn a bit more about how the staging area of Git works, why it’s necessary, how to undo changes you’ve made to the staging area, how to move and delete files in your repository, and more.

Why staging exists

Development is a messy process. What, in theory, should be a linear, cumulative construction of functionality in code, is more often than not a series of intertwining, non-linear threads of dead-end code, partly finished features, stubbed-out tests, collections of // TODO: comments in the code, and other things that are inherent to a human-driven and largely hand-crafted process.

It’s noble to think that that you’ll work on just one feature or bug at a time; that your working tree will only ever be populated with clean, fully documented code; that you’ll never have unnecessary files cluttering up your working tree; that the configuration of your development environment will always be in perfect sync with the rest of your team; and that you won’t follow any rabbit trails (or create a few of your own) while you’re investigating a bug.

Git was built to compensate for this messy, non-linear approach to development. It’s possible to work on lots of things at once, and selectively choose what you want to stage and commit to the repository. The general philosophy is that a commit should be a logical collection of changes that make sense as a unit — not just “the latest collection of things I updated that may or may not be related.”

A simple staging example

In the example below, I’m working on a website, and I want my design guru to review my CSS changes. I’ve changed the following files in the course of my work:

index.html

images/favicon.ico
images/header.jpg
images/footer.jpg
images/profile.jpg

styles/admin.css
styles/frontend.css

scripts/main.js
scripts/admin.js
scripts/email.js

Undoing staged changes

It’s quite common that you’ll change your mind about a particular set of staged changes, or you might even use something like git add . and then realize that there was something in there you didn’t quite want to stage.

touch books/management_book_ideas.md
# Content Ideas

Suggestions for new content to appear as videos:

[x] Beginning Pascal
[ ] Mastering Pascal
[x] Getting started with Symbian
[ ] Coding for the Psion V
[ ] Flash for developers
[ ] Advanced MOS 6510 Programming
git add .
git status
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
  new file:   books/management_book_ideas.md
  modified:   videos/content_ideas.md

git reset

Execute the following command to remove the change to books/management_book_ideas.md from the staging area:

git reset HEAD books/management_book_ideas.md
git log
commit 6c88142dc775c4289b764cb9cf2e644274072102 (HEAD -> master)
Author: Chris Belanger <chris@razeware.com>
Date:   Sat Jan 19 07:16:11 2019 -0400

    Adding some tutorial ideas
~/MasteringGit/ideas $ git status
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
  modified:   videos/content_ideas.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
  books/management_book_ideas.md
git commit -m "Updates book ideas for Symbian and MOS 6510"

Moving files in Git

Create the folder for the website ideas with the following command:

mkdir website
mv videos/platform_ideas.md website
~/MasteringGit/ideas $ git status
On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  deleted:    videos/platform_ideas.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
  books/management_book_ideas.md
  website/

no changes added to commit (use "git add" and/or "git commit -a")
videos/platform_ideas.md (tracked)
videos/content_ideas.md (tracked)
videos/platform_ideas.md (deleted)
videos/content_ideas.md (tracked)
website/platform_ideas.md (untracked)
mv website/platform_ideas.md videos/
git mv videos/platform_ideas.md website/
 ~/MasteringGit/ideas $ git status
On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
  renamed:    videos/platform_ideas.md -> website/platform_ideas.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
  books/management_book_ideas.md
git commit -m "Moves platform ideas to website directory"

Deleting files in Git

The impulse to just delete/move/rename files as you’d normally do on your filesystem is usually what puts Git into a tizzy, and it causes people to say they don’t “get” Git. But if you take the time to instruct Git on what to do, it usually takes care of things quite nicely for you.

rm articles/live_streaming_ideas.md
~/MasteringGit/ideas $ git status
On branch master
Your branch is ahead of 'origin/master' by 5 commits.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  deleted:    articles/live_streaming_ideas.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
  books/management_book_ideas.md

no changes added to commit (use "git add" and/or "git commit -a")
git add articles/live_streaming_ideas.md
~/MasteringGit/ideas $ git status
On branch master
Your branch is ahead of 'origin/master' by 5 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
  deleted:    articles/live_streaming_ideas.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
  books/management_book_ideas.md

Restoring deleted files

First, you need to get back to where you were. Unstage the change to the live streaming ideas file with your best new friend, git reset:

git reset HEAD articles/live_streaming_ideas.md
git checkout HEAD articles/live_streaming_ideas.md
git rm articles/live_streaming_ideas.md
git commit -m "Removes terrible live streaming ideas"
git add books/management_book_ideas.md
git commit -m "Adds all the good ideas about management"

Challenge

Challenge: Move, delete and restore a file

This challenge takes you through the paces of what you just learned. You’ll need to do the following:

Key points

  • The staging area lets you construct your next commit in a logical, structure fashion.
  • git reset HEAD <filename> lets you restore your staging environment to the last commit state.
  • Moving files around and deleting them from the filesystem, without notifying Git, will cause you grief.
  • git mv moves files around and stages the change, all in one action.
  • git rm removes files from your repository and stages the change, again, in one action.
  • Restore deleted and staged files with git reset HEAD <filename> followed by git checkout HEAD <filename>

Where to go from here?

That was quite a ride! You’ve gotten deeper into understanding how Git sees the world; building up a parallel mental model will help you out immensely as you use Git more in your daily workflow.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now