Git Lifecycle: Editing, Committing, Reverting, Etc.

Getting status

One of the most crucial commands in Git is git status. It tells you even more than its Subversion counterpart. In particular, besides the list of changed, deleted or untracked things in the filesystem, it will even tell you commands to use to get them committed or tracked. It will ignore any files or subdirectories (and the files and directories under them) that are listed in .gitignore.

Working on the latest files

Before beginning to perform fresh work in a project, you'll probably want the latest from origin master or, more frequently, from the master branch. In the subdirectory where you're planning to work, type:

$ git pull <branch>

Note that if the updates depend themselves on files in other subdirectories, you may wish to pick the subdirectory from which you do this carefully in order to get all necessary updates. Team members must be careful not to commit code that breaks the build or crashes on execution, you'd normally be safe to refresh your entire project.

Committing new work

You'll likely be doing the following to commit changes you've made whether by adding new files, modifying or deleting old ones. Using dot ('.') just ensures you cover the bases of all changes, but it's a dangerous shotgun. After you've reached a point you'd like to commit, do this:

git add . Adds everything new including scheduling modified files for commit*
git add <filename> Adds just <filename> to the change list
git status Will neatly list everything that's changed since the last commit
git commit Commits what's been added to the status.
git commit <filename> Commits just <filename>
git push <branch> You might not wish to push just anywhere let alone all the way back to master

* Beware: don't blindly shove everything into the repository! In Eclipse projects, for example, you do not want to put some files and subdirectories into the repository. It's very useful to try out git status before you perform a git commit in order to make certain what you're committing is what you intended. (This isn't different at all from Subversion.) And, if you keep tripping over files you never want tracked, add them to .gitignore.

The git push operation should require a branch name. For example, you might see:

$ git push No refs in common and none specified; doing nothing. Perhaps you should specify a branch such as 'master'. fatal: The remote end hung up unexpectedly error: failed to push some refs to 'git@swan-of-tuonela:project' $ git push origin master Counting objects: 30, done. Delta compression using up to 4 threads. Compressing objects: 100% (21/21), done. Writing objects: 100% (30/30), 4.04 MiB, done. Total 30 (delta 0), reused 0 (delta 0) To git@swan-of-tuonela:project * [new branch] master -> master

Once you've done this, Git remembers thereafter where to push to, but it's better form (because safer) to be explicit. The above will push your changes all the way to the master branch. See Git Scheme. This should not be a common operation.

Commit messages

Because of the way Git commands list commit comments, you should get into the habit of providing a short description on the commit in the first line, then elaborate on subsequent lines.

Unstaging work

Unstaging means you've added a file, new or existing, to be committed, but then discover you didn't want it in the first place. Maybe it's an intermediate file you add by accident.

If you staged a commit, but haven't committed it yet, you can back the file(s) out this way:

$ git reset -- filename [ filenames ]

Reverting work

Sometimes, you screw the pooch. Here's how to fix it. The main thing to know is that git revert is NOT the same thing as svn revert, p4 revert, etc. So don't try it. Conceptually, we're "checking out" the latest version of what's committed to the repository.

git checkout . Everything from here down--dangerous of course
git checkout <filename> Revert the named file

Reverting a whole commit and push

If you make extensive changes, commit and push to a remote, then discover that what you've done was not the best thing, here's how to fix it:

  1. Get into the branch in which you did this. If you did it in your own branch, but merged to master and pushed to remote master, this is master since that's where the "damage" was done, that's where you'll have to fix it, and you can merge the repair back into your own branch afterwards. To do this, you'll need the magic hash number of your commit. For example, ...
    master ~/acme/app $ git log commit 892ccd7b1b6c0aa3d2b159a6cef600f131b82b2b Author: Russell Bateman Date: Mon Oct 7 16:29:28 2012 -0600 Removed millions of dead, white space...
  2. Armed with the hash number of the commit, revert it:
    master ~/acme/app $ git revert 892ccd7b1b6c0aa3d2b159a6cef600f131b82b2b [master 715ccd6] Revert "Removed millions of dead, white space..." 41 files changed, 492 insertions(+), 492 deletions(-)
  3. Then, commit the change that consists of reverting the change:
    master ~/acme/app $ git push origin master Counting objects: 137, done. Delta compression using up to 4 threads. Compressing objects: 100% (65/65), done. Writing objects: 100% (75/75), 12.59 KiB, done. Total 75 (delta 49), reused 21 (delta 3) To [email protected]:acme/app.git 892ccd7..715ccd6 master -> master

Deleting and renaming work

When you no longer want a file in your project, you can remove it both from the filesystem and from the Git repository. You can also rename (or mv) a file.

git rm <filename> Remove the file from the repository and your project
git mv <filename> A shorthand that does a mv, then git rm, then get add
git rm --cached <filename> Unstage the file, but leave in your project (un-add the file)

How to remove an unneeded branch:

git branch -d <branchname> Remove the local branch
git push remote :<branchname> Remove the remote branch

Other common operations

There are myriad Git commands, too many to list here. Fortunately, there are a great deal of references returned by Google. StackOverflow is an excellent forum for asking questions about Git.

Ignoring files in Git

This means to ignore, for purposes of git status git commit and git push any file you do not wish to be committed to the master (or any other) branch. Known files such as .project and whole subdirectories such has bin or build fall under this category.

These are recorded in a file at the root of the cloned project, .gitignore. It's a file you create and populate yourself with one file or subdirectory name per line.

See Git-Eclipse Peculiarities for more on this topic.

Oops—rewording commit message

$ git commit --amend

—opens editor to last commit message so it can be modified. Result is a new commit with the same changes and the new message.

This can be useful for including files left out of the commit unintentionally including mods to files that were included, but needed to be modified again:

$ git add README.md config/routes.rb $ git rm notes.txt $ git commit --amend $ git commit --amend --author="Jack the Ripper <[email protected]>"

DANGER: this is rewriting history—safe in personal branches, but bad in community work because history is lost.