dharma017
9/13/2015 - 11:53 AM

GIT Getting Started with best practices

GIT Getting Started with best practices

Common Git Usage

Push an existing repos to Github

Assuming you have a repos on github already, issue the following commands:

cd existing_git_repo
git remote add origin git@github.com:[user]/[reponame].git
git push -u origin master

Setup Github to remember password

The instructions. Basically,

git config --global user.name "Your Name Here"
git config --global user.email "your_email@youremail.com"

Then download and setup git-credential-osxkeychain.

curl -s -O http://github-media-downloads.s3.amazonaws.com/osx/git-credential-osxkeychain
chmod u+x git-credential-osxkeychain

Issue a which git and note the path of git. Assuming it is /usr/bin/git, you have have to move to /usr/bin/ (IMPORTANT: less the git part!).

sudo mv git-credential-osxkeychain /usr/bin/

On Color Options

One of the most important configuration

git config --global color.ui true

With that, commands like git diff and git log -p looks better

What’s changed

Sometimes, you want to see what are the changes in your working directory (compared to HEAD/the last commit).

git diff somefile.py

Or you want to see what are the overall changes between the last 2 commits

git whatchanged -n 1

Then the actual code changes

git log -p somefile.py

Added new files, Updated changes, or Deleted files

If you have added new files or updated tracked files

git add .

If you have deleted files or updated tracked files

git add -u

You could do both in a single step

git add -A

What are my remotes/branches

To know,

cat .git/config

Or you can list the remotes

git remote -v

Update your repos

It’s a 2 step process. First you fetch the changes from a remote named origin

git fetch origin

Then you merge a branch master to local

git merge origin/master

Or Simply

git pull origin master

If origin is a default remote and ‘master’ is default branch, you can drop it eg. git pull.

Fix merge conflicts

This always happen when you work in teams. A very commmon question.

It usually goes like this.. You tried to update

git fetch
git pull
... not uptodate. Cannot merge.

So you commit your local changes

git add .
git commit -m "some changes"
...
Automatic merge failed; fix conflicts and then commit the result.

So you need to resolve the conflict

git mergetool -y

At this point you use the GUI (eg FileMerge) to resolve the conflicts and save. Then you commit

git add .
git commit -m "fixed conflicts"
git push

Done!

Revert a file during merge conflict

Say when you have a merge conflict, you know it should just take your file,

git checkout --ours filename.c

Or if you know yit should be their file,

git checkout --theirs filename.c

Tagging

Useful when you want to tag a version.

git tag -a v1.2

If you want to push to the tag, it works similarly like a branch.

git push origin v1.2

Delete a commit that has been pushed

This is usually when you accidentally commit wrongly.

git log
git reset --hard <sha1-commit-id>
git push origin HEAD --force

Github.com secret tricks

Read this cheat sheet. You will learn shortcut keys and referencing issues easily.

Delete a Git branch both locally and remotely

To remove a local branch from your machine:

git branch -d the_local_branch

To remove a remote branch:

git push origin :the_remote_branch

###Note When you get the error

error: unable to push to unqualified destination: the_remote_branch
The destination refspec neither matches an existing ref on the remote nor
begins with refs/, and we are unable to guess a prefix based on the source ref.
error: failed to push some refs to 'git@repository_name'
perhaps anyone else has already deleted the branch. try to synchronize your branch list with

git fetch -p

The git manual says -p, --prune

After fetching, remove any remote-tracking branches which no longer exist on the remote.

##Delete multiple branches in one command with Git.

###to delete all branches starting with hotfix- prefix

git branch | grep hotfix- | xargs git branch -d

Deploying a Git repository to remote server

git archive --format=tar origin/master | gzip -9c | ssh user@yourserver.com "tar --directory=/var/www/websearchpro/demo/foo -xvzf -"

SSH keys

An SSH key allows you to establish a secure connection between your computer and GitLab.

Before generating an SSH key, check if your system already has one by running cat ~/.ssh/id_rsa.pub. If you see a long string starting with ssh-rsa or ssh-dsa, you can skip the ssh-keygen step.

To generate a new SSH key, just open your terminal and use code below. The ssh-keygen command prompts you for a location and filename to store the key pair and for a password. When prompted for the location and filename, you can press enter to use the default.

It is a best practice to use a password for an SSH key, but it is not required and you can skip creating a password by pressing enter. Note that the password you choose here can't be altered or retrieved.

ssh-keygen -t rsa -C "admin@mail.com"

Use the code below to show your public key.

cat ~/.ssh/id_rsa.pub

Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. Please copy the complete key starting with ssh- and ending with your username and host.

Use code below to copy your public key to the clipboard. Depending on your OS you'll need to use a different command:

Windows:

clip < ~/.ssh/id_rsa.pub

Mac:

pbcopy < ~/.ssh/id_rsa.pub

GNU/Linux (requires xclip):

xclip -sel clip < ~/.ssh/id_rsa.pub

Setting Up your aliases and functions:

In windows, when you open up your Git Bash by default you are at your home directory. Inside it create a .bash_profile file (on Win8 it should be named .bashrc). If you aren't in your home directory change into it.

WHAT TO DO:

  1. Create the .bash_profile
  2. Open the .bash_profile in any editor;
  3. Add your alias into it;
  4. Add your functions into it;
  5. Save the .bash_profile;
  6. Apply changes;

HOW IT:

touch .bash_profile
notepad .bash_profile

Add your ALIASES:

# Aliases
alias g='git'
alias gst='git status'
alias gd='git diff'
alias gdc='git diff --cached'
alias gl='git pull'
alias gup='git pull --rebase'
alias gp='git push'
alias gd='git diff'
alias gc='git commit -v'
alias gc!='git commit -v --amend'
alias gca='git commit -v -a'
alias gca!='git commit -v -a --amend'
alias gcmsg='git commit -m'
alias gco='git checkout'
alias gcm='git checkout master'
alias gr='git remote'
alias grv='git remote -v'
alias grmv='git remote rename'
alias grrm='git remote remove'
alias grset='git remote set-url'
alias grup='git remote update'
alias grbi='git rebase -i'
alias grbc='git rebase --continue'
alias grba='git rebase --abort'
alias gb='git branch'
alias gba='git branch -a'
alias gcount='git shortlog -sn'
alias gcl='git config --list'
alias gcp='git cherry-pick'
alias glg='git log --stat --max-count=10'
alias glgg='git log --graph --max-count=10'
alias glgga='git log --graph --decorate --all'
alias glo='git log --oneline --decorate --color'
alias glog='git log --oneline --decorate --color --graph'
alias gss='git status -s'
alias ga='git add'
alias gm='git merge'
alias grh='git reset HEAD'
alias grhh='git reset HEAD --hard'
alias gclean='git reset --hard && git clean -dfx'
alias gwc='git whatchanged -p --abbrev-commit --pretty=medium'

#remove the gf alias
#alias gf='git ls-files | grep'

alias gpoat='git push origin --all && git push origin --tags'
alias gmt='git mergetool --no-prompt'

alias gg='git gui citool'
alias gga='git gui citool --amend'
alias gk='gitk --all --branches'

alias gsts='git stash show --text'
alias gsta='git stash'
alias gstp='git stash pop'
alias gstd='git stash drop'

# Will cd into the top of the current repository
# or submodule.
alias grt='cd $(git rev-parse --show-toplevel || echo ".")'

# Git and svn mix
alias git-svn-dcommit-push='git svn dcommit && git push github master:svntrunk'

alias gsr='git svn rebase'
alias gsd='git svn dcommit'

# these alias commit and uncomit wip branches
alias gwip='git add -A; git ls-files --deleted -z | xargs -r0 git rm; git commit -m "--wip--"'
alias gunwip='git log -n 1 | grep -q -c "\-\-wip\-\-" && git reset HEAD~1'

# these alias ignore changes to file
alias gignore='git update-index --assume-unchanged'
alias gunignore='git update-index --no-assume-unchanged'
# list temporarily ignored files
alias gignored='git ls-files -v | grep "^[[:lower:]]"'

Add your FUNCTIONS:

# functions
# Will return the current branch name
# Usage example: git pull origin $(current_branch)
#
function current_branch() {
  ref=$(git symbolic-ref HEAD 2> /dev/null) || \
  ref=$(git rev-parse --short HEAD 2> /dev/null) || return
  echo ${ref#refs/heads/}
}

function current_repository() {
  ref=$(git symbolic-ref HEAD 2> /dev/null) || \
  ref=$(git rev-parse --short HEAD 2> /dev/null) || return
  echo $(git remote -v | cut -d':' -f 2)
}

# these aliases take advantage of the previous function
alias ggpull='git pull origin $(current_branch)'
alias ggpur='git pull --rebase origin $(current_branch)'
alias ggpush='git push origin $(current_branch)'
alias ggpnp='git pull origin $(current_branch) && git push origin $(current_branch)'

# Pretty log messages
function _git_log_prettily(){
  if ! [ -z $1 ]; then
    git log --pretty=$1
  fi
}
alias glp="_git_log_prettily"

# Work In Progress (wip)
# These features allow to pause a branch development and switch to another one (wip)
# When you want to go back to work, just unwip it
#
# This function return a warning if the current branch is a wip
function work_in_progress() {
  if $(git log -n 1 2>/dev/null | grep -q -c "\-\-wip\-\-"); then
    echo "WIP!!"
  fi
}

Source the file on our new git bash

source .bash_profile

Basic Configuration:

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git config --global color.ui true
git config --global apply.whitespace nowarn

Extras:

git config --global core.editor vim
git config --global merge.tool meld

File permission issue with Mac/Linux/Windows when using git. Tell the git repository to ignore file permission globally.

git config --global core.fileMode false

Make Git Push the Current Branch by Default git config push.default current

Note:

  • Meld diff viewer only works on linux.
  • Install tortoise git for git diff viewer in Windows to work.

##Windows: http://git-scm.com/downloads

##Linux: sudo apt-get install git sudo apt-get install ssh-copy-id

##MAC OSX: brew install git brew install ssh-copy-id

##Keep your git directory clean withgit clean and git trash (Linux/Mac)

Soft alternative to git clean. Moves all unstaged files to the .trash directory for later review. First to have this command work you need to add .trash directoryto the local or global .gitignore. If you don't do that git trash will try to remove the .trash folder as well.

echo ".trash" >> .gitignore

Now add the trash git shortcut to your global aliases list:

git config --global alias.trash 'mkdir -p .trash && git ls-files --others --exclude-standard | xargs mv -f -t .trash'

And you're done. Now you can run git trash in your root of git repository and all unstaged files will be moved to the .trash subdirectory.

Create a new branch for the uncommited changes

git checkout develop
  • suppose we are working on develop branch
  • we have some changes that we don’t want to commit in this branch
  • but we need to create new branch with current changes
git stash save "your message here"
git checkout -b [newbranch]
git stash pop

##Multiple ssh public keys for one user

You can have as many keys as you desire. It's good practice to use separate private/public key sets for different realms anyway, like one set for your personal use, one for your work, etc.

First, generate two separate keypairs, one for home and one for work:

ssh-keygen -t rsa -f ~/.ssh/id_rsa.home
ssh-keygen -t rsa -f ~/.ssh/id_rsa.work

Next, add an entry to your ~/.ssh/config file to pick the key to use based on the server you connect to:

Host home
Hostname home.example.com
IdentityFile ~/.ssh/id_rsa.home
User <your home acct>

Host work
Hostname work.example.com
IdentityFile ~/.ssh/id_rsa.work
User <your work acct>

Next, append the contents of your id_rsa.work.pub into ~/.ssh/authorized_keys on the work machine, and do the same for the home key on your home machine.

Then when you connect to the home sever you use one of the keys, and the work server you use another.

Note you probably want to add both keys to your ssh-agent so you don't have to type your passphrase all the time.

How to rename a local branch ?

git branch -m <oldname> <newname>

If you want to rename the current branch, you can simply do:

git branch -m <newname>

##Rollback/Reset a Git Repository to particular commit.

###Syntax: git reset --hard <tag/branch/commit id> git diff <local branch> <remote-tracking branch>

###Example: git reset --hard c2e7af2b51

Then compare your local branch with remote branch to verify. git diff develop origin/develop

###Notes: git reset without the --hard option resets the commit history, but not the files. With the --hard option the files in working tree are also reset.

If you wish to commit that state, so remote repository also points to rolled back commit do: git push -f So, to remove a Commit That Is Already Pushed to Github

git push origin -f