This article illustrates the most common commands used in Git. If you have a little understanding of how Git works, this article will help you understand it more thoroughly.

Basic usage

The four commands above copy files between the working directory, the staging directory (also called the index), and the repository.

  • git add files puts the current file into the staging area.

  • git commit generates a snapshot of the staging area and commits it.

  • git reset - files is used to undo the last git add files, you can also use git reset to undo all staging area files.

  • git checkout - files copies files from the staging area to the working directory and is used to discard local changes.


You can enter interactive mode with git reset -p, git checkout -p, or git add -p.

You can also skip the staging area and take files directly from the repository or commit the code directly.

  • git commit -a is equivalent to running git add to add all the files in the current directory to the staging area before running it.

  • git commit files does a commit that includes the last commit plus a snapshot of the files in the working directory. And the files are added to the staging area.

  • git checkout HEAD - files rolls back to copy the last commit.


Appointment

The images are used in the form below in the latter part of the article.

The green 5-digit character indicates the ID of the commit, pointing to the parent node respectively. Branches are shown in orange, each pointing to a specific commit. The current branch is identified by the HEAD attached to it. This image shows the last 5 commits, ed489 is the latest commit. master branch points to this commit and another main branch points to the grandfather commit node.

Command Detail

Diff

There are a number of ways to see the changes between commits, here are some examples.

Commit

When you commit, Git creates a new commit with the files in the staging area, and sets the node at that point as the parent. Then the current branch is pointed to the new commit node. In the figure below, the current branch is master. before running the command, master points to ed489, and after the commit, master points to the new node f0cec and takes ed489 as its parent.

Git will do the same even if the current branch is the grandfather of a commit. In the figure below, a commit on the maint branch, the grandfather node of the master branch, generates 1800b. Thus, the maint branch is no longer the grandfather node of the master branch. At this point, merge [1] (or diff [2]) is necessary.

If you want to change a commit, use git commit -amend. git will make a new commit with the same parent as the current commit, and the old commit will be cancelled.

Another example is the separation of HEAD commits [3], covered later.

Checkout

The Checkout command is used to copy files from the history commit (or staging area) to the working directory, and can also be used to switch branches.

When given a filename (either with the -p option turned on, or with both the filename and -p option turned on), Git will copy the files from the specified commit to the staging area and to the working directory. For example, git checkout HEAD~ foo.c copies foo.c from the commit node HEAD~ (the parent of the current commit node) to the working directory and adds it to the staging area. (If no commit node is specified in the command, the contents will be copied from the staging area.) Note that the current branch will not change.

When a (local) branch is given instead of a filename, then the HEAD logo is moved to that branch (i.e., we "switch" to that branch), and the contents of the staging area and working directory will then match the commit node corresponding to HEAD.

All files in the new commit node (a47c3 in the figure below) will be copied (to the staging area and working directory); files that exist only in the old commit node (ed489) will be deleted; files that do not belong to either will be ignored and will not be affected.

If neither a filename nor a branch name is specified, but a tag, remote branch, SHA-1 value or something like master~3, you get an anonymous branch called detached HEAD (detached HEAD identifier).

This makes it easy to switch between historical versions. For example, if you want to compile version 1.6.6.1 of Git, you can run git checkout v1.6.6.1 (which is a tag, not a branch name), compile it, install it, and then switch back to another branch, say git checkout master. ", the behavior is slightly different, as described below.

HEAD identifies the commit operation when it is in the detached state

When HEAD is in a detached state (not attached to any branch), the commit operation proceeds normally, but does not update any named branches. (You can think of this as updating an anonymous branch.)

Once you switch to another branch thereafter, say master, then this commit node will (probably) never be referenced again and will then be discarded. Note that there will be nothing referencing 2eecb after this command.

However, if you want to save this state, you can use the command git checkout -b name to create a new branch.

Reset

The Reset command points the current branch to another location, and selectively changes the working directory and index. It is also used to copy files from the historical repository to the index without moving the working directory.


If no option is given, then the current branch points to that commit. If the -hard option is used, then the working directory is also updated, and if the -soft option is used, then both remain unchanged.

If the version number of the commit point is not given, then the default is HEAD. this way, the branch pointing remains the same, but the index is rolled back to the last commit, and the same goes for the working directory if the -hard option is used.

If a filename is given (or the -p option), then it works pretty much the same as checkout with a filename, except that the index is updated.

Merge

The Merge command merges different branches together. Before merging, the index must be the same as the current commit. If the other branch is the grandfather node of the current commit, then the merge command will do nothing. The other case is if the current commit is the grandfather node of another branch, which results in a fast-forward merge. The pointing is simply moved and a new commit is generated.

Otherwise it is a true merge. The default takes the current commit (ed489 shown below) and another commit (33104) and their common grandfather node (b325c) and does a three-way merge [4]. The result is to first save the current directory and index, and then do a new commit with the parent node 33104.

Cherry Pick

The cherry-pick command "copies" a commit node and does an identical new commit on the current branch.

Rebase

Diffusion is an alternative to the merge command. Merge combines two parent branches for a single commit, and the commit history is not linear. A diff repeats the history of the other branch on the current branch, and the commit history is linear. Essentially, it is a linearized automatic cherry-pick.

The above commands are done in the topic branch, not the master branch, replaying on the master branch and pointing the branch to the new node. Note that the old commit is not referenced and will be recycled.

To limit the scope of the rollback, use the -onto option. The following command replays the last few commits on the master branch for the current branch since 169a6, i.e. 2c33a.

There is also git rebase -interactive to make it easier to do complex operations such as dropping, reordering, modifying, and merging commits. There is no image to reflect these, see here for details: git-rebase(1)[5].

Technical Notes

The file contents are not really stored in the index (.git/index) or commit objects, but are stored separately as blob files in the database (.git/objects) and are verified with SHA-1 values. The index file lists the associated blob file and other data with an identifier.

For commits, they are stored as a tree, also identified by the for hash value. The tree corresponds to a folder in the working directory, and the tree or blob object contained in the tree corresponds to the corresponding subdirectory and file. Each commit stores the identifier of its next level tree.

If you commit with detached HEAD, then the last commit is referenced by the reflog for HEAD. But it expires after a while and is eventually recycled, much like git commit -amend or git rebase.

Related links

  1. ​http://marklodato.github.io/visual-git-guide/index-zh-cn.html#merge
  2. http://marklodato.github.io/visual-git-guide/index-zh-cn.html#rebase
  3. http://marklodato.github.io/visual-git-guide/index-zh-cn.html#detached
  4. http://en.wikipedia.org/wiki/Three-way_merge
  5. http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html#_interactive_mode