Git/Introduction

Here, we will introduce the simplest git commands: creating a new repository, adding and committing files, removing files, reverting bad commits, throwing away uncommitted changes, and viewing a file as of a certain commit.

Creating a git repository
Creating a new git repository is simple. There are two commands that cover this functionality:, and. Cloning a pre-existing repository will be covered later. For now, let's create a new repository in a new directory: $ Initialized empty Git repository in:
 * 1) /home/username/myrepo/.git/ on Linux.
 * C:/Users/username/myrepo/.git/ on Windows.

If you already have a directory you want to turn into a git repository: $ $

Taking the first example, let's look what happened: $ $  .git

The totality of your repository will be contained within the  directory. Conversely, some SCMs leave files all over your working directory (eg,,  ,  , etc.). Git refrains, and puts all things in a subdirectory of the repository root aptly named.

Remark: to set the default directory where Git will point at each opening, under Windows right click on the shortcut, and change the path of the field called "start in".

Checking Your Status
To check the status of your repo, use the command. For example, a newly-created repo with no commits in it as yet should show this:

$ On branch master Initial commit nothing to commit (create/copy files and use "git add" to track)

Get into the habit of frequent use of, to be sure that you’re doing what you think you’re doing. :)

Adding and committing files
Unlike most other VCSs, git doesn't assume you want to commit every modified file. Instead, the user adds the files they wish to commit to the staging area (also known as the index or cache, depending on which part of the documentation you read). Whatever is in the staging area is what gets committed. You can check what will be committed with or.

To stage files for the next commit, use the command. $ hack hack hack... $ # # # nothing added to commit but untracked files present (use "git add" to track)
 * 1) On branch master
 * 1) Initial commit
 * 1) Untracked files:
 * 2)   (use "git add ..." to include in what will be committed)
 * 1) 	file.txt

This shows us that we're using the branch called "master" and that there is a file which git is not tracking (does not already have a commit history). Git helpfully notes that the file can be included in our next commit by doing : $ $  # # # #
 * 1) On branch master
 * 1) Initial commit
 * 1) Changes to be committed:
 * 2)   (use "git rm --cached ..." to unstage)
 * 1) 	new file:  file.txt

After adding the file, it is shown as ready to be committed. Let's do that now: $ [master (root-commit) be8bf6d] My first commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 file.txt

In most cases, you will not want to use the  form - instead, leave it off to have   opened so you can write a proper commit message. We will describe that next, but in examples, the  form will be used so the reader can easily see what is going on.

You can use  to automatically stage all changed and untracked files for inclusion in the next commit. Once a file is being tracked,  will stage it if it has changed.

reset
If you change your mind about staging a file, and you haven’t committed yet, you can unstage it with the simplest form of the command: $ to unstage just the one file, or $ to remove everything in the staging area.

has many more functions than this, for example:
 * To cancel the two latest commits without touching the files:.
 * To cancel the two latest commits and their modifications into the files:.
 * To cancel the two last operations on the branch:  (which uses  ). This can be used to cancel an undesired reset.

To exclude certain untracked files from being seen by, read on...

restore
comes back to a version of the file specified in parameter.

Excluding files from Git
Often there are files in your workspace that you don't want to add to the repository. For example, emacs will write a backup copy of any file you edit with a tilde suffix, like filename~. Even though you can manually avoid adding them to the commit (which means never using ), they clutter up the status list.

In order to tell Git to ignore certain files, you can create an ignore file, each line of which represents a specification (with wildcards) of the files to be ignored. Comments can be added to the file by starting the line with a blank or a # character.

For example:


 * 1) Ignore emacs backup files:

app/cache
 * 1) Ignore everything in the cache directory:

Git looks for an ignore file under two names:
 * .git/info/exclude — this is specific to your own personal copy of the repository, not a public part of the repository.
 * .gitignore — since this is outside the .git directory, it will normally be tracked by Git just like any other file in the repository.

What you put in either (or both) of these files depends on your needs. .gitignore is a good place to mention things that everybody working on copies of this repository is likely to want to be ignored, like build products. If you are doing your own personal experiments that are not likely to concern other code contributors, then you can put the relevant ignore lines into .git/info/exclude.

Note that ignore file entries are only relevant to the  and   (add all new and changed files) commands. Any files you explicitly add with  will always be added to the repository, regardless of whether their names match ignore entries or not. And once they are added to the repository, changes to them will henceforth be automatically tracked by.

Good commit messages
Tim Pope writes about what makes a model Git commit message:

Short (50 chars or less) summary of changes More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of an email and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); tools like rebase can get confused if you run the two together. Write your commit message in the present tense: "Fix bug" and not "Fixed bug." This convention matches up with commit messages generated by commands like git merge and git revert. Further paragraphs come after blank lines. - Bullet points are okay, too - Typically a hyphen or asterisk is used for the bullet, preceded by a  single space, with blank lines in between, but conventions vary here - Use a hanging indent Let’s start with a few of the reasons why wrapping your commit messages to 72 columns is a good thing.
 * Git log doesn’t do any special wrapping of the commit messages. With the default pager of, this means your paragraphs flow far off the edge of the screen, making them difficult to read. On an 80 column terminal, if we subtract 4 columns for the indent on the left and 4 more for symmetry on the right, we’re left with 72 columns.
 * converts a series of commits to a series of emails, using the messages for the message body. Good email netiquette dictates we wrap our plain text emails such that there’s room for a few levels of nested reply indicators without overflow in an 80 column terminal.

Vim users can meet this requirement by installing my vim-git runtime files, or by simply setting the following option in your git commit message file: :set textwidth=72

For Textmate, you can adjust the “Wrap Column” option under the view menu, then use ^Q to rewrap paragraphs (be sure there’s a blank line afterwards to avoid mixing in the comments). Here’s a shell command to add 72 to the menu so you don’t have to drag to select each time: $ defaults write com.macromates.textmate OakWrapColumns '( 40, 72, 78 )'

More important than the mechanics of formatting the body is the practice of having a subject line. As the example indicates, you should shoot for about 50 characters (though this isn’t a hard maximum) and always, always follow it with a blank line. This first line should be a concise summary of the changes introduced by the commit; if there are any technical details that cannot be expressed in these strict size constraints, put them in the body instead. The subject line is used all over Git, oftentimes in truncated form if too long of a message was used. The following are just a handful of examples of where it ends up:


 * shows a terse history mapping containing the commit id and the summary
 * provides the summary for each commit in the editor it invokes
 * If the config option <tt>merge.summary</tt> is set, the summaries from all merged commits will make their way into the merge commit message
 * uses summary lines in the changelog-like output it produces
 * ,, and related tools use it as the subject for emails
 * , a local history accessible intended to help you recover from mistakes, get a copy of the summary
 * , a graphical interface which has a column for the summary
 * Gitweb and other web interfaces like GitHub use the summary in various places in their user interface.

The subject/body distinction may seem unimportant but it’s one of many subtle factors that makes Git history so much more pleasant to work with than Subversion.

Removing files
Let's continue with some more commits, to show you how to remove files: $ $  # # no changes added to commit (use "git add" and/or "git commit -a")
 * 1) On branch master
 * 2) Changed but not updated:
 * 3)   (use "git add ..." to update what will be committed)
 * 4)   (use "git checkout -- ..." to discard changes in working directory)
 * 1) 	modified:  file.txt

Although git doesn't force the user to commit all modified files, this is a common scenario. As noted in the last line of, use   to commit all modified files without reading them first: $ [master e633787] My second commit 1 files changed, 1 insertions(+), 0 deletions(-)

See the string of random characters in git's output after committing (bolded in the above example)? This is the abbreviation of the identifier git uses to track objects (in this case, a commit object). Each object is hashed using SHA-1, and is referred to by that string. In this case, the full string is <tt>e6337879cbb42a2ddfc1a1602ee785b4bfbde518</tt>, but you usually only need the first 8 characters or so to uniquely identify the object, so that's all git shows. We'll need to use these identifiers later to refer to specific commits.

To remove files, use the "rm" subcommand of git: $ rm 'file.txt' $ # # $  .  ..  .git
 * 1) On branch master
 * 2) Changes to be committed:
 * 3)   (use "git reset HEAD ..." to unstage)
 * 1) 	deleted:   file.txt

Note that this deletes the file from your disk. If you only want to remove the file from the git repository but want to leave the file in your working directory, use.

$ [master b7deafa] Removed file.txt 1 files changed, 0 insertions(+), 2 deletions(-) delete mode 100644 file.txt

Reverting a commit
To revert a commit with another, use : $ Finished one revert. [master 47e3b6c] Revert "My second commit" 1 files changed, 0 insertions(+), 1 deletions(-) $ .  ..  file.txt  .git

You can specify any commit instead of HEAD. For example:
 * The commit before HEAD:
 * The commit five back:
 * The commit identified by a given hash:

Resetting a commit
provides the same options as, but instead of creating a revert commit, it just cancels the commit(s) and lets the file(s) uncommitted.

To cancel a reset, use:.

Throwing away local, uncommitted changes
To throw away your changes and get back to the most recently-committed state: $

As above, you can specify any other commit: $

If you only want to reset one file (where you have made some stupid mistake since the last commit), you can use $ This will delete all changes made to that file since the last commit, but leave the other files untouched.

Get a specific version of a file
To get a specific version of a file that was committed, you'll need the hash for that commit. You can find it with : $ commit 47e3b6cb6427f8ce0818f5d3a4b2e762b72dbd89 Author: Mike.lifeguard <myemail@example.com> Date:  Sat Mar 6 22:24:00 2010 -0400 Revert "My second commit" This reverts commit e6337879cbb42a2ddfc1a1602ee785b4bfbde518. commit e6337879cbb42a2ddfc1a1602ee785b4bfbde518 Author: Mike.lifeguard <myemail@example.com> Date:  Sat Mar 6 22:17:20 2010 -0400 My second commit commit be8bf6da4db2ea32c10c74c7d6f366be114d18f0 Author: Mike.lifeguard <myemail@example.com> Date:  Sat Mar 6 22:11:57 2010 -0400 My first commit

Then, you can use : $ hack hack hack... more stuff

Git Checkout Is Not Subversion Checkout
If you are coming to Git after having used the Subversion centralized version-control system, you may assume that the checkout operation in Git is similar to that in Subversion. It is not. While both Git and Subversion let you check out older versions of the source tree from the repository, only Subversion keeps track of which revision you have checked out. Git does not. will only show you that the source tree does not correspond to the current branch HEAD; it will not check whether it corresponds to some prior commit in the history.

<TT>diff</TT> and <TT>patch</TT>: The Currency of Open-Source Collaboration
It is important to understand early on the use of the <TT>diff(1)</TT> and <TT>patch(1)</TT> utilities. <TT>diff</TT> is a tool for showing line-by-line differences between two text files. In particular, a unified diff shows added/deleted/changed lines next to each other, surrounded by context lines which are the same in both versions. Assume that the contents of <TT>file1.txt</TT> are this: this is the first line. this is the same line. this is the last line.

while <TT>file2.txt</TT> contains this: this is the first line. this line has changed. this is the last line.

Then a unified diff looks like this: $ --- file1.txt   2014-04-18 11:56:35.307111991 +1200 +++ file2.txt  2014-04-18 11:56:51.611010079 +1200 @@ -1,3 +1,3 @@ this is the first line. -this is the same line. +this line has changed. this is the last line. $

Notice the extra column at the start of each line, containing a “-” for each line that is in the first file but not in the second, a “+” for each line that is in the second file but not the first, or a space for an unchanged line. There are extra lines, in a special format, identifying the files being compared and the numbers of the lines where the differences were found; all this can be understood by the <TT>patch</TT> utility, in order to change a copy of <TT>file1.txt</TT> to become exactly like <TT>file2.txt</TT>:

$ $  patching file file1.txt $ $

Notice how the second <TT>diff</TT> command no longer produces any output: the files are now identical!

This is how collaborative software development got started: instead of exchanging entire source files, people would distribute just their changes, as a unified <TT>diff</TT> or in <TT>patch</TT> format (same thing). Others could simply apply the patches to their copies. And provided there were no overlaps in the changes, you could even apply a patch to a file that had already been patched with another <TT>diff</TT> from someone else! And so this way changes from multiple sources could be merged into a common version with all the new features and bug fixes contributed by the community.

Even today, with version-control systems in regular use, such diffs/patches are still the basis for distributing changes. and both produce output which is compatible with , and can be correspondingly understood by <TT>patch</TT>. So even if the recipient of your patches isn’t using Git, they can still accept your patches. Or you might receive a patch from someone who isn’t using Git, and so didn't use <TT>git-format-patch</TT>, so you can’t feed it to to automatically apply it and save the commit; but that’s OK, you can use, or even <TT>patch</TT> itself on your source tree, and then make a commit on their behalf.

Conclusion
You now know how to create a new repository, or turn your source tree into a git repository. You can add and commit files, and you can revert bad commits. You can remove files, view the state of a file in a certain commit, and you can throw away your uncommitted changes.

Next, we will look at the history of a git project on the command line and with some GUI tools, and learn about git's powerful branching model.

Git/Premiers pas Git/Przypadki