A commit is the Git equivalent of an SVN revision, i.e., a set of changes that is stored in the repository along with a commit message. The Commit command is used to store working tree changes in the local repository, thereby creating a new commit.
Since every repository starts with an initial commit, and every subsequent commit is directly based on one or more parent commits, a repository forms a ‘commit graph ‘ (or technically speaking, a directed, acyclic graph of commit nodes), with every commit being a direct or indirect descendant of the initial commit. Hence, a commit is not just a set of changes, but, due to its fixed location in the commit graph, also represents a unique repository state.
Normal commits have exactly one parent commit, the initial commit has no parent commits, and the so-called merge commits have two or more parent commits.
o ... a merge commit | \ | o ... a normal commit | | o | ... another normal commit | / o ... yet another normal commit which has been branched | o ... the initial commit
Each commit is identified by its unique SHA-ID, and Git allows checking out every commit using its SHA. However, with SmartGit you can visually select the commits to check out, instead of entering these unwieldy SHAs by hand. Checking out will set the HEAD and working tree to the commit. After having modified the working tree, committing your changes will produce a new commit whose parent will be the commit that was checked out. Newly created commits are called heads because there are no other commits descending from them.
Putting It All Together
The following example shows how commits, branches, pushing, fetching and (basic) merging play together.
Let’s assume we have commits
origin/master both point to
HEAD points to
other words: The working tree has been switched to the branch master.
This looks as follows:
o [> master][origin/master] C | o B | o A
Committing a set of changes results in commit
D, which is a child of
master will now point to
D, hence it is one commit ahead of the
o [> master] D | o [origin/master] C | o B | o A
As a result of a Push, Git sends the commit
D to the origin
repository, moving its
master to the new commit
D. Because a remote
branch always refers to a branch in the remote repository,
origin/master of our repository will also be set to the commit
o [> master][origin/master] D | o C | o B | o A
Now let’s assume someone else has further modified the remote repository
E, which is a child of
D. This means the
the origin repository now points to
E. When fetching from the origin
repository, we will receive commit
E and our repository’s
origin/master will be moved to
o [origin/master] E | o [> master] D | o C | o B | o A
Finally, we will now merge our local
master with its tracking branch
origin/master. Because there are no new local commits, this will
master fast-forward to the commit
E (see Fast-forward Merge).
o [> master][origin/master] E | o D | o C | o B | o A