Even though i have touched Git
many weeeks ago, but i never totally figure it very clearly. Even for now…
Before demonstrate and analyze every single Git statement usage. I would like to explain some terminologies first:
- Tracked files are files that were in the last snapshot; they can be unmodified, modified, or staged.
- Untracked files are everything else - any files in your working directory that were not in your last
snapshot and are not in your staging area. Every file in your working directory can be in one of two states:
tracked
oruntracked
. - Committed means that the data is safely stored in your local database.
Modified
means that you have changed the file but have not committed it to your database yet. - Staged means that you have marked a modified file in its current version to go into your next commit snapshot.
- Git directory is where Git stores the metadata and object database for your project. This is the most important part of Git, and it is what is copied when you clone a repository from another computer.
- Working directory is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify.
- Staging area is a simple file, generally contained in your
Git directory
, that stores information about what will go into your next commit. It’s sometimes referred to as theindex
, but it’s becoming standard to refer to it as the staging area.
####The basic Git workflow goes something like this:
- Modify files in your working directory.
- Stage the files, adding snapshots of them to your staging area.
- Submit a commit, which takes the files as they are in the staging area and stores that snapshot permanently to your Git directory.
####Let’s demonstrate the workflow using a simple example:
####Checking the Status $ git status # On branch master nothing to commit (working directory clean) When we do actions in Git, nearly all of them only add data to the Git database. So we add a new file named README. $ git status # On branch master # Untracked files: # (use “git add …” to include in what will be committed) # # README nothing added to commit but untracked files present (use “git add” to track) It says README file is untracked, because it’s under the Untracked files heading in your status output. And Git tell us how to track the untracked files. Let’s do it. ####Tracking New Files $ git add README $ git status # On branch master # Changes to be committed: # (use “git reset HEAD …” to unstage) # # new file: README # The git add command takes a path name for either a file or a directory; if it’s a directory, the command adds all the files in that directory recursively. ####Staging Modified Files If you change a previously tracked file and run the ‘git status’ again, you get something like “Changed but not updated” — which means that a file that is tracked has been modified in the working directory but not yet staged. To stage it, you run the git add command (it’s a multipurpose command — you use it to begin tracking new files, to stage files, and to do other things like marking merge-conflicted files as resolved). Let’s run git add now to stage the changed file, and then run git status again, you will get: “Changes to be committed”. So If you modify a file after you run git add, you have to run git add again to stage the latest version of the file. ####Viewing Staged and Unstaged Changes If the git status command is too vague for you — you want to know exactly what you changed, not just which files were changed — you can use the git diff command. That command compares what is in your working directory with what is in your staging area. The result tells you the changes you’ve made that you haven’t yet staged. ####Committing Changes Now that your staging area is set up the way you want it, you can commit your changes. Remember that anything that is still unstaged — any files you have created or modified that you haven’t run git add on since you edited them — won’t go into this commit. They will stay as modified files on your disk. $ git commit -m “Story 182: Fix benchmarks for speed” ####Skipping the Staging Area If you want to skip the staging area, Git provides a simple shortcut. Providing the -a option to the git commit command makes Git automatically stage every file that is already tracked before doing the commit, letting you skip the git add part:$ git commit -a -m ‘added new benchmarks’ ####Removing Files To remove a file from Git, you have to remove it from your tracked files (more accurately, remove it from your staging area) and then commit. The git rm command does that and also removes the file from your working directory so you don’t see it as an untracked file next time around: $ git rm readme.txt Another useful thing you may want to do is to keep the file in your working tree but remove it from your staging area. In other words, you may want to keep the file on your hard drive but not have Git track it anymore. This is particularly useful if you forgot to add something to your .gitignore file and accidentally added it, like a large log file or a bunch of .a compiled files. To do this, use the –cached option: $ git rm –cached readme.txt ####Moving Files Thus it’s a bit confusing that Git has a mv command. If you want to rename a file in Git, you can run something like $ git mv file_from file_to and it works fine. In fact, if you run something like this and look at the status, you’ll see that Git considers it a renamed file: $ git mv README.txt README $ git status # On branch master # Your branch is ahead of ‘origin/master’ by 1 commit. # # Changes to be committed: # (use “git reset HEAD …” to unstage) # # renamed: README.txt -> README # However, this is equivalent to running something like this: $ mv README.txt README $ git rm README.txt $ git add README Git figures out that it’s a rename implicitly, so it doesn’t matter if you rename a file that way or with the mv command. The only real difference is that mv is one command instead of three — it’s a convenience function. ####Viewing the Commit History After you have created several commits, or if you have cloned a repository with an existing commit history, you’ll probably want to look back to see what has happened. The most basic and powerful tool to do this is the git log command. One of the more helpful options is -p, which shows the diff introduced in each commit. You can also use -n, which limits the output to only the last two entries: $ git log -p -2 ####Changing Last Commit One of the common undos takes place when you commit too early and possibly forget to add some files, or you mess up your commit message. If you want to try that commit again, you can run commit with the –amend option: $ git commit –amend As an example, if you commit and then realize you forgot to stage the changes in a file you wanted to add to this commit, you can do something like this: $ git commit -m ‘initial commit’ $ git add forgotten_file $ git commit –amend All three of these commands end up with a single commit — the second commit replaces the results of the first. ####Unstaging a Staged File $ git add . $ git status # On branch master # Changes to be committed: # (use “git reset HEAD …” to unstage) # # modified: README.txt # modified: benchmarks.rb # Right below the “Changes to be committed” text, it says use git reset HEAD … to unstage. So, let’s use that advice to unstage the benchmarks.rb file: $ git reset HEAD benchmarks.rb benchmarks.rb: locally modified $ git status # On branch master # Changes to be committed: # (use “git reset HEAD …” to unstage) # # modified: README.txt # # Changed but not updated: # (use “git add …” to update what will be committed) # (use “git checkout – …” to discard changes in working directory) # # modified: benchmarks.rb # The command is a bit strange, but it works. The benchmarks.rb file is modified but once again unstaged. ####Unmodifying a Modified File What if you realize that you don’t want to keep your changes to the benchmarks.rb file? How can you easily unmodify it — revert it back to what it looked like when you last committed (or initially cloned, or however you got it into your working directory)? Luckily, git status tells you how to do that, too. In the last example output, the unstaged area looks like this: # Changed but not updated: # (use “git add …” to update what will be committed) # (use “git checkout – …” to discard changes in working directory) # # modified: benchmarks.rb # $ git checkout – benchmarks.rb $ git status # On branch master # Changes to be committed: # (use “git reset HEAD …” to unstage) # # modified: README.txt # ####Showing Remotes $ git remote -v ####Adding Remote Repositories $ git remote origin $ git remote add pb git://github.com/paulboone/ticgit.git $ git remote -v origin git://github.com/schacon/ticgit.git pb git://github.com/paulboone/ticgit.git ####Fetching and Pulling from Your Remotes $ git fetch [remote-name] $ git pull Running git pull generally fetches data from the server you originally cloned from and automatically tries to merge it into the code you’re currently working on. ####Pushing to Your Remotes When you have your project at a point that you want to share, you have to push it upstream. The command for this is simple: git push [remote-name] [branch-name]. If you want to push your master branch to your origin server (again, cloning generally sets up both of those names for you automatically), then you can run this to push your work back up to the server: $ git push origin master This command works only if you cloned from a server to which you have write access and if nobody has pushed in the meantime. If you and someone else clone at the same time and they push upstream and then you push upstream, your push will rightly be rejected. You’ll have to pull down their work first and incorporate it into yours before you’ll be allowed to push. ####Inspecting a Remote If you want to see more information about a particular remote, you can use the git remote show [remote-name] command. If you run this command with a particular shortname, such as origin, you get something like this: $ git remote show origin * remote origin URL: git://github.com/schacon/ticgit.git Remote branch merged with ‘git pull’ while on branch master master Tracked remote branches master ticgit ####Removing and Renaming Remotes If you want to rename a reference, in newer versions of Git you can run git remote rename to change a remote’s shortname. For instance, if you want to rename pb to paul, you can do so with git remote rename: $ git remote rename pb paul $ git remote origin paul It’s worth mentioning that this changes your remote branch names, too. What used to be referenced at pb/master is now at paul/master. If you want to remove a reference for some reason — you’ve moved the server or are no longer using a particular mirror, or perhaps a contributor isn’t contributing anymore — you can use git remote rm: $ git remote rm paul $ git remote origin