Git Basics
Git Basics
Get the Repository
git clone https://github.com/rails/rails.git cd rails
This copies the salsa repo at the given location to the salsa sub-directory.
To download updates from your original repository, and merge changes into your current branch:
git pull
To update the repo, and merge the changes yourself on your master branch
git fetch get merge origin # This is also called a "fast forward" merge for newer changes
To send updates to branches on the original repo:
git push
Switching Branches
What branches exist?
git branch # Lists local branches git branch -a # Lists all (local + remote) branches git branch -v # Shows last commit message
To create the remote staging branch as your staging branch, use the checkout -b option:
git checkout -b staging origin/staging
To switch back to the master branch
git checkout master
To create an new branch, for issues, features, or experimentation:
git checkout -b 1287-purge-feature
You can do this before or after you start working, your uncommitted changed will be kept with the new branch. Your current branch is the starting point for the new branch, usually the branch in which you will merge the changes back (staging).
Sharing the Branch
If you want to send your branch up to the original repository to share it with others:
git push origin 1234-feature-branch
In order to pull changes to that branch back into your repository, you must add this to your .git/config file on the root of the repo:
[branch "1234-feature-branch"] remote = origin merge = refs/heads/1234-feature-branch
To remove the remote branch:
git branch -d -r origin/1234-feature-branch
Finishing the Branch
When you are done with the branch, merge it back into the original branch, and delete it
git checkout staging git merge --no-ff 1234-feature-branch git branch -d 1234-feature-branch
The —no-ff (no fast-forward) merge option keeps the group of commits to the source branch in a separate path, and creates a “merge” point. Fast forward merges will not show the branching history.
The -d option deletes the branch if merged. If you do not want to merge it, blow it away with the -D option
git branch -D 1234-experimental-branch
Branch Naming Conventions
Long-lived branches are common names
master: Production branch. staging: Beta release branch, recent features and fixes for next release
Feature and issue branches incorporate the tracker ticket number and description
ticket-issue_feature-title-of-feature-or-issue 1234-feature-title 1234-hotfix-title 1234-issue-title
Making Changes
Switch to the branch you wish to commit the change. Edit away.
What files are changed?
git status
this shows known, modified files in the first section, then (new) untracked files, and deleted files. Deleted files are removed from the repository on commit.
What are my changes I am about to commit?
git diff [--color] [--word-diff]
To restore a file to its original state, or copy from another branch:
git checkout filename # Discard changes to it git checkout branch filename # Cherry-pick this file from another branch/tag/commit
Rename, move and delete files:
git mv source destination # Rename or new location git rm files rm files # git detects deleted files and will delete them too
Staging your Commit
Commits to all known files can be made with:
git commit -a git commit -a -m'commit message'
If you want to commit only certain changed files:
git commit file file ...
If you want to also add changed files, or new files to the commit (and repository), use ‘git add’. They are then staged and committed with the next commit action.
git add file file ... git commit
You can examine and accept/decline each chunk of change in each file. This is useful to make sure any unintended test code is not committed, and to review your work.
git commit -p
Commit Message Conventions
Refer to a tracker ticket number and type on the commit message, or start the commit message with the following action verbs: fixed, added, hotfix (I know), removed, updated, or similar.
fixes #1234 feature-name issue-description adds #1234 feature-name description hotfix #1234 issue description
Try to include the feature-name as the process, program or webpage name.
The commit will print out the branch name, commit hash, and commit message. Copy and paste this into the tracker ticket when resolving the issue, allowing the change to be identified and inspected later if necessary.
Workflow
Update your repository and merge changes into your current branch, switch to the starting branch (staging) and create your work branch:
git pull git checkout staging git checkout -b 1234-feature-name
Sometimes, you want to rebase your work on the current state of the starting branch. Rebasing removes your commits, fast-forwards the initial branch point to the current HEAD (last commit) of the starting branch. It them “replays” your commits onto the new starting point.
git pull git rebase
After finishing your changes, test and commit, then prepare to merge back into the starting branch
git commit ... git checkout staging git pull # Updates repository and fast-forwards branch git merge --no-ff 1234-feature-name git push # Sends merged branch upstream git branch -d 1234-feature-name
Interrupted Development
By keeping your work separate, you can switch back to the staging branch for a hotfix at anytime
git stash # Stores uncommitted changes for later git checkout staging git pull
Make and test your changes…
git commit -a -m'hotfix #1111 ...' git push git checkout 1234-feature-name git stash apply # Restores uncommitted changes
Large-scale Workflow
My workflow understand came from this great post
The git-flow extensions help implement and enforce this style of workflow.
Inspecting the Repository
Use the git log command to display the commit chain of a branch. On the command line it will be
git log [options] [since..until] [branch] [filenames] git log git log files git log staging bl-manage git log --pretty=oneline --abrev-commit --graph --color
You can also specify the starting and ending points to display. “since” and “until” here can be commit hashes, tags, HEAD, or not specified to indicate the beginning of time or current commit (HEAD)
since.. # From commit/tag to HEAD since..until # Between commits/tags ..until # Up until the point commithash # This commit only
Which files changed?
Use the whatchanged command to show the changed files for the commits
git whatchanged [options] [since..until] [branch] [filenames] git whatchanged --pretty=oneline --abbrev-commit c260028 Fixed redirect after login (php reg globals) :100755 100755 04816ea... 51a264a... M www/mlm/controller/home.php :100755 100755 0b36ac1... 0869628... M www/mlm/main.php
Inspecting with git diff
The git diff command can show differences between two commits for all files or given files.
git diff [options] [since..until] [branch] [filenames] git diff # Uncommitted changes git diff [since..until] git diff --word-diff=color # Readable diffs with red (removed) and green (added)
Inspecting a commit
The ‘git show’ command prints information from the log and diff commands together
git show [options] [since..until] [branch] [filenames]
The tig command
The tig package is a ncurses-based git browser. Very awesome.
tig tig [options] [since..until] [branch] [filenames]
Use it to review commits, and show the revisions.
GUI Tools
Git comes with a Tcl/Tk browser:
git gui
There are several options for each platform:
- gitweb: A web application
- getalist: web application
- gitorious: open-sourced web hosting platform
- gitx: Mac OS X client
Releasing
Release are merges of changes in the staging branch into the master branch.
git checkout master git merge --no-ff staging git tag -a v1.2.3 # Opens commit message in editor for details git push --tags
To update a repo, simply pull, or checkout to a tag
git fetch # Downloads new tags, branches and commits git pull # Does a fetch, and merges into current branch git checkout v1.2.3 # Sets the repo to the given tag or commit hash
Due to the distributed topology of git, once tags are pushed, they should be considered permanent.
Hotfixes
Hotfixes are added directly to the master branch, as they need to be separate from the other changed already present in the staging branch. The change should be applied to both branches, using the cherry-pick command.
git commit -a -m'hotfix #1234: can not delete records' [staging 8cf5623] hotfix #1234: can not delete records git pull git checkout master git cherry-pick 8cf5623 git push
This will copy the commit to the master branch. It will have different hash on the new branch because it is applied to a different point in the repository.
Creating a Repository
Take a project directory and make it a git repo.
cd project git init # Creates .git subdirectory to hold repo vi .gitingnore # Create file of filename patterns to ignore *.swp # Like vim swap files *.log # and log files git add . # Adds files in directory to staged commit git commit -m'Initial commit to git' # Commit project
Now let’s share it on our network
ssh example.com cd /path/to/git/repos/ git clone --bare originalhost:path/to/project project.git touch project.git/git-daemon-export-ok # if using git-daemon instead of ssh chmod -R g+w project.git # Allow everyone to write to the repo
Point your project repo to use this new one as the origin
cd project git config remote.origin.url ssh://example.com/path/to/project.git
Git Resources
Git command offer a —help option to show the man page
git pull --help man git-pull
- Pro Git Book: Free, online book
- Git User’s Manual: From the git team
- Git Guide: on stackoverflow
- Git Magic: A nice introduction
Sample ~/.gitconfig
[user] name = Your Name email = mailbox@example.com [core] editor = vim [color] diff = auto status = auto branch = auto ui = auto grep = auto ui = auto [alias] co = checkout com = commit cp = cherry-pick c = commit -a br = branch -v b = branch -v st = status s = status d = diff --color-words sh = show --color-words l = log --pretty=oneline --abbrev-commit --graph ll = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative uncommit = reset --soft HEAD^ amend = commit --amend -C HEAD master = checkout master staging = checkout staging devel = checkout development ;send = push origin listpost-edit [merge] tool = vimdiff [rerere] enabled = 1