Developing with git – Basics – Basic Commands



Developing with git – Basics – Basic Commands

1 0


git-slides

Slides for a talk on git

On Github zfjagann / git-slides

Developing with git

How to use git to improve your day-to-day development tasks

Basics

Commit

  • A list of changes
  • Zero or more parent commits
  • A message

Commits can be created with the commit command and viewed with the log command.

Commits also have a SHA-1 name, which are 40 characters long, but can be abbreviated to anything longer than 4 characters.

Branch

A pointer to a commit

Branches can be managed with the branch command and changed with the checkout command.

Remote

The location of another git repository

Remotes can be managed with the remote command and synchronized with the commands fetch, pull, and push.

Head

A pointer to the current branch

The HEAD behaves like a branch, and is moved by the checkout command.

Index

A cache between the working directory and the repository

The index can be modified with the commands add and reset.

Repository

  • A repository of blobs and trees
  • A list of branches
  • A list of remotes
  • An index
  • A working directory
  • A HEAD

The local repository lives in the .git directory.

Basic Commands

Init

Initializes a new git repository in the current directory.

$ git init
Initialized empty Git repository in /Users/zeal/git/.git/
                        

Clone

Copies the contents of a repository

$ git clone git@github.com:zfjagann/Demo.git
Cloning into 'Demo'...
remote: Counting objects: 53, done.
remote: Compressing objects: 100% (32/32), done.
remote: Total 53 (delta 9), reused 49 (delta 5)
Receiving objects: 100% (53/53), 4.68 KiB, done.
Resolving deltas: 100% (9/9), done.

Add

Adds changes to the index

$ git add updated-file

Status

Lists information about the workspace, index, and repository

$ git status
# On branch new
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   updated-file
#

Commit

Creates a commit with the contents of the index

$ git commit -m 'Added updated-file'
[master 1797f98] Added updated-file
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 updated-file
                        

Log

Lists a history of commits in the repository.

$ git log
commit fb61a552913bf97de6055c823bafb463375f3492
Author: zeal <zeal@skybox.com>
Date:   Wed Jun 12 18:26:59 2013 -0700

    Added readme.
                        
Can do some amazing stuff with log and fancy formatting.

Branching

Create a branch

Use branch to create a new branch.

$ git branch feature-branch
                        
* fb61a55 - Added readme. (HEAD, feature-branch, master)
                        

Switch branches

Use checkout to change branches.

checkout -b is an alias that will create and switch to a new branch

$ git checkout feature-branch
Switched to branch 'feature-branch'
                        

Commit into a branch

When changes are committed, the are committed to HEAD.

$ git commit -m 'Added a new feature.'
[my-branch c4dcc14] Added a new feature.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 feature.rb
                        
* c4dcc14 - Added a new feature. (HEAD, feature-branch)
* fb61a55 - Added readme. (master)
                        

Diverging

When changes are committed into two branches independently, the branches diverge.

$ git checkout master
$ git add quick-fix.rb
$ git commit -m 'Added a quick fix.'
[master 127d4e1] Added a quick fix.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 quick-fix.rb
                        
* 127d4e1 - Added a quick fix. (HEAD, master)
| * c4dcc14 - Added a new feature. (feature-branch)
|/
* fb61a55 - Added readme.
                        

Converging

There are two ways to join branches:

  • merge
  • rebase

Merge

A merge joins the two diverged tree segments with a new commit combining their changes.

Merge in action

Before

* 127d4e1 - Added a quick fix. (HEAD, master)
| * c4dcc14 - Added a new feature. (feature-branch)
|/
* fb61a55 - Added readme.
                            

$ git checkout master
$ git merge feature-branch
Merge made by the 'recursive' strategy.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 feature.rb
                        

After

*   aaac857 - Merge branch 'feature-branch' (HEAD, master)
|\
| * c4dcc14 - Added a new feature. (feature-branch)
* | 127d4e1 - Added a quick fix.
|/
* fb61a55 - Added readme.
                            

Merge commits muddle history, and are difficult to read.

Fast Forward

If one of the tree segments doesn't contain changes the merge is called a fast-forward.

$ git checkout feature-branch
$ git merge master
Updating c4dcc14..aaac857
Fast-forward
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 quick-fix.rb
                        
*   aaac857 - Merge branch 'feature-branch' (HEAD, feature-branch, master)
|\
| * c4dcc14 - Added a new feature.
* | 127d4e1 - Added a quick fix.
|/
* fb61a55 - Added readme.
                        
This occurs when the common ancestor of two commits is one of the two commits. A fast-forward is the ideal type of merge, where one side can simply be moved forward in the history.

Rebase

A rebase will replay history from one branch on top of another.

Rebase in action

Before

* 127d4e1 - Added a quick fix. (master)
| * c4dcc14 - Added a new feature. (HEAD, feature-branch)
|/
* fb61a55 - Added readme.
                            

$ git checkout feature-branch
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Added a new feature.
                        

After

* d44f56b - Added a new feature. (HEAD, feature-branch)
* 127d4e1 - Added a quick fix. (master)
* fb61a55 - Added readme. (origin/master)
                            

Using rebase

Rebase destructively changes your commit history, so can be dangerous to use.

Do not rebase commits that have been pushed to a remote.

Interactive Rebase

The rebase command has an interactive mode that allows for manipulating commits in various ways:

  • squash
  • modify
  • remove
  • split

Remotes

Remotes are how git keeps track of linked repositories.

Remote

The remote command can be used to list servers or modify them.

$ git remote
origin
$ git remote -v
origin  git@github.com:zfjagann/Demo.git (fetch)
origin  git@github.com:zfjagann/Demo.git (push)
$ git remote add other git@github.com:rpk/Demo.git
$ git remote -v
origin  git@github.com:zfjagann/Demo.git (fetch)
origin  git@github.com:zfjagann/Demo.git (push)
other   git@github.com:rpk/Demo.git (fetch)
other   git@github.com:rpk/Demo.git (push)
$ git rm other
$ git remote
origin
                        

Remote Branches

Branches on remotes are represented locally as:(remote)/(branch)

For example:origin/master

Tracking Branches

Local branches can be setup to track remote branches.

$ git checkout --track origin/new-branch
Branch new-branch set up to track remote branch new-branch from origin.
Switched to a new branch 'new-branch'
                        
Tracking is git's way of making sure that the branches are synchronized.

Push

The push command will transfer local commits to a remote repository.

$ git push origin master
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 269 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:zfjagann/Demo.git
   fb61a55..25c1f9f  master -> master
                        
Tracking is git's way of making sure that the branches are synchronized.

Fetch

The fetch command will fetch all commits at each repository to their local remote branches.

$ git fetch
remote: Counting objects: 34, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 23 (delta 19), reused 15 (delta 11)
Unpacking objects: 100% (23/23), done.
From github.com:zfjagann/Demo.git
   a198ec0..00e78cd  master     -> origin/master
                        

Pull

The pull command will internally do a fetch immediately followed by a merge.

$ git pull origin master
From ../Demo2
 * branch            master     -> FETCH_HEAD
Updating fb61a55..25c1f9f
Fast-forward
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file
                        

Pull rebase

The pull command can be told to do a rebase instead by passing the --rebase argument.

$ git pull --rebase origin master
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 2 (delta 0), reused 1 (delta 0)
Unpacking objects: 100% (2/2), done.
From ../Demo2
 * branch            master     -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: Added second file.
                        

Fetch vs. Pull

The pull command allows for ease of use. The fetch command allows for inspection and manual merging of remote changes.

Workflows

A workflow is a procedure for collaborating on a project with git.

Atlassian has descriptions for four common workflows on their workflows page.

Submodules

A submodule is a repoisitory nested within another repository.

Creating a Submodule

Submodules can be created with the submodule command.

$ git submodule add git@github.com:zfjagann/Demo.git
Cloning into 'Demo'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Receiving objects: 100% (3/3), done.

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   .gitmodules
#   new file:   Demo
                        

Foreach

Using the foreach command, you can run a given command in each submodule of the current repository.

$ git submodule foreach git rev-list -n 2 HEAD
Entering 'Demo'
d44f56b7831ec44dd087ea499e5896c5d85475df
127d4e1e43ba59ba10190b1716dfa6975086952e
                        
This is extremely useful and can be used to branch all projects in a group. Also, the --recursive flag allows for nested submodules.

Foreach

Using the foreach command, you can run a given command in each submodule of the current repository.

$ git submodule foreach git rev-list -n 2 HEAD
Entering 'Demo'
d44f56b7831ec44dd087ea499e5896c5d85475df
127d4e1e43ba59ba10190b1716dfa6975086952e
                        
This is extremely useful and can be used to branch all projects in a group. Also, the --recursive flag allows for nested submodules.

Cool Git Features

Alias

Aliases can be used to shorted long commands.

Similar to bash aliases.

Bisect

Bisect is a tool to binary-search through bash history to find the cause of a bug.

Suppose you know a feature is broken, and you know it worked 6 months ago. Bisect will allow you to binary-search through the history to find the commit that caused the bug.

Log

The log command can be used to print pretty branch graphs.

$ git log --graph --oneline
*   e58a2a2 Merge branch 'master' of git@github.sky:DataSystems/JanusCommon.git
|\
| * 17348c7 fixing broken migration
| * 1e23c55 [Janus-683] flattened camera into collection
| * 031b1c1 [JANUS-115] Added resource for reserving SAWs.
* |   051ded6 Merge branch 'master' of git@github.sky:DataSystems/JanusCommon.git
|\ \
| |/
| * f4f6ced [JANUS-686] Updated window generator to generate SkyNode windows.
| * 71ae40f Updated pkg file to include populateGroundStations
| * ae31ec8 Correct customer Ids
| *   4a54f3b Merge branch 'saw_windows'
| |\
| | * 23f7001 Renamed populate script.
* | | 8292b66 [NEXUS-6] WIP
|/ /
* | 709e857 [NEXUS-6] WIP on sending SkyNode Blackouts Event JSON from Janus to Nexus
* | 3609edd [NEXUS-6] configuring TELNotifier to pass SkyNode Blackout Window info to Nexus
* |   42fc224 Merge branch 'master' of git@github.sky:DataSystems/JanusCommon.git