Skip to content

Instantly share code, notes, and snippets.

@mrkline
Last active October 12, 2015 08:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrkline/3998315 to your computer and use it in GitHub Desktop.
Save mrkline/3998315 to your computer and use it in GitHub Desktop.
Git usage

##The Basics

###Installation

####Windows Users

First off, get msysgit (download here). It is the official Windows Git distribution, and comes with a terminal that has your standard bash commands as well as Git.

If you prefer GUIs, SourceTree is the way to go. This guide is for using Git on the command line, but TortoiseGit has equivalent windows for all commands.

####Mac Users

You can get the Mac installer for Git here.

####Linux Users

Install Git via your standard package manager (apt-get, yum, pacman).

###Basic Setup:

You will want to give Git your name and email - they are used to sign your commits. These commands will do that:

git config --global user.name "John Doe"
git config --global user.email johndoe@domain.com

Global Git settings are stored in a .gitconfig file in your home directory. Settings can also be set on a repository-specific basis. See the man page of git config for a full list of options. Some other useful ones include:

  • color.ui - Set this to "auto" in order for Git to provide colored output.
  • core.autocrlf and core.safecrlf - Git can do automatic line-ending conversions to ensure that line endings in files are consistent regardless of which OS each developer is working in.
  • diff.tool - The command git difftool will use a diff tool to show changes. Use this to set the tool to be used.
  • aliases - Custom commands can be created (see git graph below)

###Cloning a repository:

git clone <repo location> <dir>

will clone a Git repository in a new directory inside your current directory. Leaving out <dir> will cause it to name the folder after the Git repository. For example,

git clone git@github.com:torvalds/linux.git

clones Github's mirror of the Linux kernel into a directory named "linux".

###Committing files:

Git's commit process involves two steps:

  1. Add new files, add changes for existing files (both with git add <files>), and/or remove files (with git rm). These changes are put in a staging area called the index.

  2. Call git commit to commit the changes.

Git commit will open up a text editor to provide a commit message. You can set this editor to whatever you want by changing the core.editor option with git config.

Alternatively, you can use git commit -m <message> to supply the commit message without opening the text editor.

Other useful commit tricks:

git commit -a lets you commit changes you have made to files already under Git control without having to take the step of adding the changes to the index. You still have to add new files with git add.

git add -p lets you commit specific parts of files you have changed. This is useful if you have made a bunch of changes that you think would be best split into several commits.

###Pushing your changes:

To push your changes up to a server (such as Github), use

git push <server name> <branch>

Adding -u will make this server the default one to push to for this branch. If you have cloned the repository as described above, the server will default to the location you cloned the repository from (nicknamed "origin") and the branch will default to the master branch. In other words, if you have followed this guide's instructions in cloning, git push will suffice. You can set up Git to push to multiple servers if you want, but that is a more advanced topic. Branches will be discussed later in this guide.

###Pulling from the server:

If you are working on multiple machines and want to update your local repository to what the server has, you use

git pull <server name> <branch>

Similarly to push, the server name and branch should have sane defaults, so git pull should suffice. Git pull is actually shorthand for doing two things:

  1. Calling git fetch, which updates the local copy of what the server has. Such branches are called "remote" branches because they are mirroring remote servers.

  2. Calling git merge, which merges what the remote branch has with what you have. If your commit history is the same as the server's commit history, you will be automatically fast-forwarded to the latest commit on the server. If your history does not match (maybe someone else has pushed commits since you last synced), the two histories will be merged.

It is not a bad idea to get into the practice of using these two commands instead of git pull. This way you can check to make sure that the server contains what you would expect before merging.

###Examining history

The command git log shows the history of your current branch. Note that each commit is identified by a SHA-1 hash. The author, commit date, and commit message follow. A more useful command is

git log --graph --oneline --decorate

which provides a display similar to TortoiseGit's log window. It shows the following:

  • The first 7 digits of each commit's SHA-1 hash (enough to be unique)
  • The --graph option shows how any branches (if there are others) fork off from the current branch.
  • The --oneline option shows only the first line of each commit message
  • The --decorate option shows all commit labels (branches and tags)

It may be convenient to alias this command as git graph by doing the following:

git config --global alias.graph 'log --graph --oneline --decorate'

Now typing git graph will run git log --graph --oneline --decorate. git graph and git log may be given the --all flag in order to view all branches instead of just the current one. Adding --stat to one of these commands is also useful - it shows which files each commit changed and how many lines were changed in each file.

###Dealing With Merges

Merges happen when you pull, as a result of a rebase operation, and when you merge one branch into another. Like other version control tools, when Git cannot automatically merge a commit, it turns to you. See this section of the Git Book for an explanation on how to resolve merge conflicts. If you screw up and would like to back out of the merge, you can usually abort the merge using the --abort flag with whatever command started the merge (e.g. git merge --abort, git pull --abort, git rebase --abort).

###What to Commit

Generally, you should commit

  • Actual code files (.cpp, .java, .cs, etc.)
  • Project files (Makefiles, .sln files in the case of Visual Studio, etc.)

You should not commit

  • Files generated by your code or IDE (.o object files for C and C++, .class files for Java, bin/ and obj/ folders for Visual Studio, etc.). This also includes your output program.
  • User-specific options (such as .suo files for Visual Studio)

To make Git automatically ignore files, you can create a text file named .gitignore. Each line should contain a file name, directory name, or pattern to ignore. For example, a .gitignore for a Visual Studio C# project might contain

bin/
obj/
*.suo

and a .gitignore for a C++ Makefile-based project might contain

*.o
<program name>

The .gitignore is automatically applied to the directory it is in and any sub-directories.

##Git Trickery

The above commands only provide the basics. The real power and convenience in Git come from leveraging its local commits and fast branching. A typical Git workflow looks like this:

  1. Create and check out a branch to add a feature.
  2. Make as many commits as you would like on that branch while developing that feature.
  3. Squash, rearrange, and edit your commits until you are satisfied with the commits enough to push them to the central server and make them public.
  4. Merge your branch back into the main branch.
  5. Delete your branch, if you desire.
  6. Push your changes to the central server.

###Creating a branch

git branch <branch name>

can be used to create a branch that will branch off the current commit. After it has been created, you should switch to it using

git checkout <branch name>

A simpler method is to do both in one step with

git checkout -b <branch name>

To see a list of branches, and which branch is currently checked out, use

git branch

###A word on commits

Many of the following commands take commits as arguments. A commit can be identified by any of the following:

  • Its 40-digit SHA-1 hash (the first 7 digits are usually sufficient to identify it uniquely)
  • Any commit label such as a branch or tag name
  • The label HEAD always refers to the currently checked-out commit (usually the head of the branch, unless you used git checkout to jump back in history to an old commit)
  • Any of the above plus ~ to refer to previous commits. For example, HEAD~ refers to one commit before HEAD and HEAD~5 refers to five commits before HEAD.

###Commits as checkpoints

In Subversion and other older, centralized version control systems, commits are permanent - once you make them, they are there on the server for everyone to see. In Git, your commits are local and you can combine, rearrange, and edit them before pushing them to the server. This gives you more flexibility and lets you use commits as checkpoints. Commit early and commit often.

###Editing the previous commit

git commit --amend

allows you to modify the previous commit. The contents of the index will be applied to it, allowing you to add more files or changes you forgot to put in. You can also use it to edit the commit message, if you would like.

###Squashing, rearranging, and changing history

git rebase -i <commit>

will bring up a list of all commits between <commit> and the present, including HEAD but excluding <commit>. This command allows you rewrite history. To the left of each commit, a command is specified. Your options are as follows:

  • The "pick" command (the default) uses that commit in the rewritten history.
  • The "reword" command lets you change a commit message without changing the commit's contents.
  • The "edit" command will cause Git to pause during the history rewrite at this commit. You can then modify it with git commit --amend or insert new commits.
  • The "squash" command will cause a commit to be folded into the previous one. You will be prompted to enter a message for the combined commit.
  • The "fixup" command works like squash, but discards the message of the commit being squashed instead of prompting for a new message.
  • Commits can be erased from history by deleting them from the list of commits
  • Commits can be re-ordered by re-ordering them in the list. When you are done modifying the list, Git will prompt you to resolve any resulting merge problems (after doing so, continue rebasing with git rebase --continue)

When you are done modifying the list, Git will perform the desired actions. If Git stops at a commit (due to merge conflicts caused by re-ordering the commits or due to the "edit" command), use git rebase --continue to resume. You can always back out of the rebase operation with git rebase --abort.

IMPORTANT: Only use this command on local commits that have not yet been pushed to anybody else. Modifying commits that are on the central server will cause merge problems for obvious reasons.

Side note: Vim makes these rebase operations really simple since lines can be cut and pasted with few keystrokes.

##Additional Links

Getting Started - Git Basics

Try Git - a quick (15 minute), interactive Git tutorial by Github

All Git man pages - manual pages for every Git command

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment