GitHub Intermediate

Leveraging Git and GitHub from the command line

Please note: This class and curriculum have now become a part of the two day GitHub for Developers course.

GitHub Intermediate

Important command line skills and problem solving processes

Configuring your Git environment

Establish important and useful settings for efficient command line use.

git config --global "Your Name"
git config --global "Email Address"

git config --global color.ui auto
git config --global core.autocrlf [input|true]

git config --global core.editor

  1. Verify the current value of your username and email address as known by Git.
  2. If needed, set your username and email address using the git config command.
  3. If on Windows, set your line ending behavior to core.autocrlf true
  4. If on Mac, set your line ending behavior to core.autocrlf input
  5. List out all your remaining Git configuration values.


Git is configured through name-value pairs saved in an INI file format. The name-value pairs can be read and written through the git config command.

Git’s configuration is saved in one of three plain text files and one of three levels. It is easily editable with a text editor and portable to other machines by copying the configuration files.


Your name and email address are configured locally in Git and are attached to each commit. Set these accurately to receive proper attribution for your work.

These are the very first Git elements often suggested to set. If not set, Git will fall back to an automatically derived name and email from the host machine’s network node name.

To see the current settings, individually query two configuration values:

$ git config --global
Firstname Lastname

$ git config --global

If using the GitHub for Windows or GitHub for Mac GUIs, these values are set, system-wide, by each GUI’s configuration dialog.

To set the same values to apply to any of your repositories:

$ git config --global "your name"
$ git config --global "your@email"

For a configuration specific to just the repository folder you’re currently working in:

$ git config "[your full name]"
$ git config "[]"


Git configuration can be set at one of the three aforementioned levels. The most common is global, and is used for all cross-repo but per-user settings.

Level Precedence Location
system lowest alongside the git binary
global middle in your home directory as .gitconfig
local highest in your project’s .git/config file

To use each of the scopes in a setting or getting action of config, simply provide the scope’s name alongside the config action:

$ git config --system [name] [value]
$ git config --global [name] [value]
$ git config --local [name] [value]

Listing configuration

Listing the current configuration is as easy as asking for the entire set of name-value pairs:

# List all configuration for a given scope
$ git config --list --[scope]

Further reading


Starting on the command line

Begin versioning project content from existing content or from a fresh start.

# Initialize a new project

$ git init [projectname]

#Initialize from inside a top level directory

$ cd [project-directory]
$ git init

#Acquire with default repository name

$ git clone [repository-url]

# Acquire with preferred, optional name

$ git clone [url] [optional-folder-name]


Git provides an easy way to start versioning any prototype, prose or project with a terse command line recipe. Just initialize a local repository and create a top level project directory:


Versioning via the command line

Explore the advantages of Git’s staging area and commit process.

$ git status
$ git add [filename]
$ git commit -m "[your description]"




Three stages of versioning

Three stages of versioning

Three stages of versioning

  1. Create a new file and save it in the repository folder
  2. Stage the file using the add command
  3. Preserve the changes in history with the commit command



Comparing pending and existing changes

Maximize file comparison abilities of Git with historical and un-committed change review.


$ git diff


$ git diff --staged


$ git diff HEAD

# By specific file

$ git diff [file-path]

  1. Compare changes of modified files with respect to history
  2. Compare staged modifications with respect to history
  3. Compare unstaged changes to staged changes of the file


Git advocates precision in each commit’s contents and commit message. This is facilitated by easy review of in-flight changes prior to making them permanent.

The simplest invocation of diff is the most common. It displays the difference of the files that have been modified.

$ git diff

Git also creates a distinction between what is modified and unselected and what has been staged for commit. A single diff option switch allows for the inspection of each of these two groups of changes.

$ git diff --staged

The default line-level difference indicators are sometimes insufficient for prose and small variable-name changes. There is, however, an option to instruct Git to perform and highlight intra-line comparisons.

# Highlight word changes on lines
$ git diff --color-words

Diff, by default, performs comparisons on all modified files. If inspection of just a subset is called for, diff accepts a precise or wildcard-ed filename or path as an option.

# By specific file
$ git diff [file-path]


Reviewing historical changes

Assess committed content across all known versions and narrow searches with filtering options.

$ git log

$ git log --oneline

  1. Review default commit history output
  2. Refine history output with option switches
  3. Isolate history listing by branch or starting point


Git can look back at the history of each commit to see when a change took place, who made the change, or what the change contained.

$ git log

Some simple option flag additions to the log command can make the output more concise.

 Simple commit summaries
$ git log --oneline

And if displaying the full contents of the change and word-level comparisons are helpful, there are option switches for that too.

 Option switches common with `diff`
$ git log --patch --color-words


Organizing history for optimal workflows

Harness Git’s fast branching features for efficiently switching between work effort.

# Create a new branch from the current one

$ git branch [branch-name]

# Switch to a specified branch

$ git checkout [branch-name]

# List all local branches

$ git branch

Merge strategies





  1. Create a topic branch from master or gh-pages
  2. Change branches and understand where commits will be associated
  3. Merge and combine histories of separate branches


Typical workflows always begin with a branch, no matter how small or grand the level of effort might be or the number of commits involved.

 List branches, identify current branch
$ git branch

 Create a new branch from current branch
$ git branch [name]

 Switch to a different branch
$ git checkout [name]

Option switches:

 Rename any branch
$ git branch -m [current-name] [new-name]

 Delete a *reachable* branch
$ git branch -d [name]

 Delete whether or not reachable
$ git branch -D [name]

The final step to bringing the history of a branch into the current one is performed by merging it.

 Integrate history of specified branch into current one
$ git merge [branch]


Interacting with distributed repositories

Go beyond local history interactions and synchronize histories on an as-needed, controlled basis.

Distributed repos


  1. Understand Fork repository model
  2. Create your own Fork of any accessible repository
  3. Submit Pull Requests from a Fork


Git is capable of working with 0 to N remotes. 0 means the local repo only knows about the local file system, 1 represents a more traditional centralized model, and 1+N is an example of the “distributed” multi-mastered facet of a DVCS.

 List remote "bookmarks", if any
$ git remote

Additional remotes (bookmarks) are added as a name-URL-value pair. The default name, as established by a clone operation, is origin. Another common remote name is upstream, seen most frequently in Fork-and-Pull workflows.

 Add a remote "bookmark"
$ git remote add [name] [url]

Retrieval behavior configuration

Adjusting the pull to rebase any local changes on top of inbound ones from the upstream branch:

$ git config --[scope] pull.rebase true

Retrieving branch changes in discrete steps:

 Retrieve all remote branches, then list them
$ git fetch
$ git branch -a

Retrieving changes

If retrieval and incorporation are desired to happen in one action, pull is the appropriate command:

 Retrieve remote history and update working tree
$ git pull

If the goal is branch retrieval prior to disconnecting from a network, preserving the changes for later review and incorporation, use fetch:

 Only retrieve remote history
$ git fetch

$ git branch -r

Git also facilitates ad-hoc branch retrieval to FETCH_HEAD with or without a remote:

 Temporarily retrieve a repository's branch from a remote
$ git fetch [remote] [branch]

 Temporarily retrieve a repository's branch from a URL
$ git fetch [url] [branch]

Sharing changes

A fully-specified push can indicate both the destination and contents:

 Send branch's commit to specific remote
$ git push [remote] [branch]

If a push pattern for a given branch will be used frequently, -u instructs Git to remember the remote and branch association.

 Setup and publish branch's commits
$ git push -u [remote] [branch]

The most simplistic invocation of push leverages tracking as set up by a clone or push -u to suggest which branches to transmit:

 Send any local commits to the tracking upstream branch
$ git push

Crafting shortcuts & efficiencies

Improve Git interactions with custom commands, preferred option flags, and specialized outputs.

  1. Setup example aliases for command line efficiency
  2. Create your own Git command alias and option switch combination


 Shortcut to output commit history
$ git config --global alias.l "log --oneline --stat"
 Quick graph of commit history and branches
$ git config --global "log --graph --all --oneline --decorate"
 Shortcut to repository status
$ git config alias.s "status -s"

Understanding versioned file lifecycle

Remove, move, and rename files with full version control coverage.

States of tracking

States of tracking

States of tracking

States of tracking

States of tracking

  1. Understand the tracking states of new, modified, deleted, and renamed paths
  2. Use the rm command to permanently delete files from future version control tracking
  3. Use the mv command to relocate file paths and rename files
  4. Apply the similarity-index concept to a real-world example
  5. Stage any file state by the add command’s option switches


Files in Git transition through well-defined states of tracking.

Adding files

 Stage all updated files
$ git add -u [file|pattern]
 Stage all files no matter the state
$ git add -A [file|pattern]

Removing files

When already tracked files are no longer needed, they can be removed from tracking and from the file system:

 Permanently delete file, stage for commit
$ git rm [file]

If there’s a reason to preserve the file on disk after removing it from tracking, Git facilitates this behavior variant:

 Stop version tracking, stage for commit
$ git rm --cached [file]

Moving files

 Change the path of a file
$ git mv [path]

Reviewing moved files

 Show history including those with prior path names
$ git log --stat -M


Undoing any versioned changes

Rewind, collapse, or discard one or a range of versioned changes with a few simple commands.

  1. Use revert to generate a new commit undoing history
  2. Understand the effects of reset



Revert is the kindest undo functionality. It creates a new inverse commit and links back to the old one in the proposed commit message:

 Create a new commit undoing the patch in that specified
$ git revert [commit]


 Move current branch's HEAD to point in history
$ git reset [commit|branch|tag]

Reset offers a plethora of options to adjust the nuances of its restorative behavior:

 Move HEAD, keep changes in staging
$ git reset --soft [commit|branch|tag]

 Move HEAD, keep changes, clear staging area
$ git reset --mixed [commit|branch|tag]

# Move HEAD, discard all uncommitted changes
$ git reset --hard [commit|branch|tag]

Recovering from anything

Restore content from versioned history.

  1. Understand the side effects of reset and discarding commit history
  2. Using the reflog to review orphaned commits and past, local repo interactions
  3. Applying reflog commit SHAs and the reset to recover lost commits


Reviewing historical states

$ git reflog

Restoring a historical state

$ git reset --[option] HEAD@{[n]}

Specific paths

$ git checkout HEAD@{[n]} -- [path]

Additional Resources

Table of Contents