Git In Brief

In brief, GIT is a source code management (scm) system that works with a local repository and zero or more remote repositories. For a typical corporate installation, there will be local repository for each developer, and one remote that is the shared common "gold source" repository.

Getting a local copy of a shared remote repository is done through an action called "cloning", and results in a complete copy of the remote repository on your local system.

As GIT allows for multiple remotes, it is important to understand that each remote will have a symbolic name in your local repository. By default, the source repository that a local repository is cloned from is called "origin", so most commands working with the central repository will use "origin" as part of the command.

For organizations that keep a single common "gold source" repository, the Standard Operating Procedure will be to clone the shared common repository from the "gold source" to your local machine, making "origin" point to the gold source.

The shared common repository (in the organizations central GIT repo) is the equivalent to the svn repositories in a typical SVN installation.

Most git commands (checkout, commit, branch, etc) work against your local repository, with some special commands (push, fetch, pull) to move those changes to and from remote repositories (ie the shared repo). It is important to remember this distinction.. changes that have been committed (to local) but not pushed (to common remote) are at risk for loss upon damage to your local machine.

Typical Workflow

  1. Get the project: git clone {repo_url}

  2. Make change to the code

  3. Commit changes (to local): git commit

  4. repeat steps 2-3, remembering this is only local!

  5. push changes to remote: git push origin

  6. fetch and merge changes from remote: git fetch origin; git merge origin OR git pull origin

  7. repeat from #2

Fetch and merge may occur at various points of the cycle. multiple local commit before push is not a requirement, simply here as an example. Many developers working on branches that are specific to their work will always push every commit.

One good reason for multiple commits before a push would be on a shared branch, it would allow delaying the fetch/merge of other developers changes while still keeping your history.

Important Notes

Commands

AKA Git for SVN Users

Get Developer copy of Remote Repository

Initial retrieval from remote repo, rough equivalent to svn:checkout

git clone [--recursive] {repo_url} {localdir}

For example:

$ git clone --recursive ssh://{user@host}/path/repo_name.git repo_name

If you have already cloned a repo without using "–-recursive", you can update submodules by running:

$ git submodule update --init --recursive

Working with Branches

See:Basic Branching and Merging for detailed information

Switch working directory to a (different) LOCAL branch ­ svn:switch

See Working with a remote branch below for how to work with a branch that exists on the remote that you did not create..

git checkout {branch}

Working with a remote branch

If a branch you wish to work with already exists in the remote source (origin), you must make a local branch before you can work and commit to it!

git checkout -b {branch} --track {remote}/{branch}

for example..

git checkout -b feature-CHANGE-ID --track origin/feature-CHANGE-ID

GIT PROVIDES A USEFULL SHORTCUT FOR THIS!

As this is a common scenario, Git handles the following request with a bit of extra smarts:

git checkout {branch}

If this is executed in a repository that has no local branch {branch} but a remote branch matching {branch} in exactly one remote, then it is translated to the above command!

So, assuming there is no local branch named "feature-CHANGE-ID", and you have one remote (ie "origin") and a branch with that name exists in that remote, then the shortcut would be

git checkout feature-CHANGE-ID

If the remote branch was created/updated after your clone

You will need to "fetch" the remote first, to populate your local pointers to the remote

git fetch origin
git checkout {branch}

Create a branch (local)

This is a local only branch! Similar in purpose to svn:cp {repo_url}/trunk {repo_url} / branches/{branch}

git branch {branch}

Create a branch from another branch or from a tag

git branch {new-branch} {source-branch|source-tag}

Create branch and switch working dir to branch in one command

git checkout -b {branch}

Push local branch to remote repo

When you are ready to share your changes with the team, or make them available for deployment (in a central repository configuration typical of corporate development) you will "push" them to a shared repo.

git push -u {remote} {branch}

Deleting Branches

Delete a local branch

Does not delete any remote branch being tracked by the local branch!

git branch -d {branch}

Delete remote branch

git push {remote} --delete {branch}

Example: git push origin --delete release-1.91.0

Note: after deleting remote branches, its a good idea to run "git fetch -p" to prune any local branches that are tracking remote branches that no longer exist.

Committing changes

Committing changes is actually a three step process with git:

  1. Stage Changes - make GIT aware of the changes
  2. Commit the changes - commit the changes to your local repository and generate new versions
  3. Push the changes - send the changes to the remote (origin) repository.

Stage

Git does not automatically recognize a changed file as ready to commit - you must tell git to include the changed file, aka stage the commit.

To see changed files and what git has "staged" execute

git status

The output will look like

$ git status
# On branch master
# Untracked files:
#    (use "git add <file>..." to include in what will be committed)
#
# newFile

Note the "newFile" under Untracked files - this indicates any files that have changed, but are not staged - ie git commit will not include it.

To stage the change, execute

git add newFile

the status will be updated to indicate the staged change

$ gitaddnewFile
# On branch master
# Changes to be committed:
#    (use "git reset HEAD <file>..." to unstage)
#
# newfile: newFile
#

Note newFile is now listed under "changes to be committed"

Commit

After files are staged, they need to be committed to GIT - remember, commit is a local action with GIT

git commit

Push Changes to remote

git push

This will send committed changes in your local current working branch to the remote repository

git push {remote} {branch}

Will send a specified branch to the specified remote repo.

Reverting Changes

See: Undoing Things

Revert Local (uncomitted/unstaged) changes

Revert changes to modified files

git reset ‐‐hard

Remove all untracked files and directories.

git clean‐fd

Unstage staged changes

This unstages modified files but does NOT revert the changes

git reset HEAD {file}

Revert Comitted Changes

Find bad commit or commits with git log, and revert specific commit with git revert

Note that this creates a NEW commit with the change in the specified commit removed.

$ git log

commit: 2b92077395ff02f1a4f295c3d657c4280c8a0f65

Author: Joe Developer <<Joe.Developer@example.com>>

Date: Thu Sep 5 15:10:062013‐0700

   Comment developer gave when making code commit.

$ git revert 2b92077395ff02f1a4f295c3d657c4280c8a0f65

don't forget to push your changes

Completly remove a committed change that has never been pushed

Warning : this should only be used if you are sure the change to be reverted has NEVER been pushed to another repository! Use reset with care as it is one of the few GIT commands that can cause loss of your work.

I the case of an unintended commit, you may wish to make like the commit never happened. To completely remove local-only commits, you can reset your local

git reset [--soft|--hard] <commit>

Documentation pending. will include may be {remote}/{branch}

Revert changes to submodule when you deleted it

git submodule update

_OR_

git submodule update ‐‐init

Synchronizing Development with updated source branch

Occasionally you will be working on a branch and the source branch will be updated after your branch was created. If you need these changes reflected on your branch, you need to merge those changes to your branch.

To do so, you must first update your local copy of the source branch, then merge the changes to your new branch.

git checkout {source-branch}
git pull
git checkout {target-branch}
git merge {source-branch}

Conflics can occur during the merge! If there are no conflicts, the merge will be automatically comitted. If a conflict is detected, the merge will halt, allowing you to resolve the conflicts before continuing. See How Conflicts Are Presented and HOW TO RESOLVE CONFLICTS for information on how to read and resolve conflicts.

Cherry pick a commit

Sometimes you want to pull just one change from another branch to your working code. This is done through cherry-picking

Determine which commit you want and obtain its hash (git log or your git web tools)

git cherry-pick 895055224d89a36be1b2548e139d962fd8f73d9b

Maintaining the Shared Repository

Commands that are useful to maintaining the common repository

Find all branches merged to a particular branch

git branch -r --merged {branch}

This is particularly useful to see if a feature branch has been merged to a release branch for a release, or master before deleting a "completed" branch

git branch -r --merged origin/master

git branch -r --merged origin/release-1.XX.X

Get a list of commits in one branch but not another Thanks to Jerod Santo for this tip

git log --left-right --graph --cherry-pick --oneline {source_branch}...{target_branch}