Git Command Quick Reminder


Git is a source code management system that emphasizes speed, data integrity and distributed non-linear workflows.


INSTALLING GIT


$ aptitude install git-core # git basic tools.

NOTE: In Debian Unstable
$ aptitude install git


gitk graphic tool.
$ aptitude install gitk # this graphic tool allows us to browse a git repo.



INITIALIZE A REPOSITORY


$ git init # Creates an empty repository in current directory, or reinitializes an existing one.
$ git init directory_name # Creates an empty repo in directory_name directory.

$ git clone remote_url # clone a remote repo. Passing as argument a local directory this command clones a local repo.

$ git clone --depth 1 git://git.sip.router.org/sip-router kamailio # clones sip-router source code, creating a local directory named kamailio. "depth 1" option means it only takes one revision history. That reduces the amount of history to download, but it disallows cloning, fetching, pushing or pulling from this repo. Then, it is only suitable to generate patches.

$ git clone source_repo dest_repo # clones a local repository source_repo in another local repository dest_repo,
if both are directories.
$ git clone file:///path/to/source/repo file:///path/to/dest/repo # another way to specify local directories.
This way we are sure git does not use hard links when cloning source repo.
$ git clone --no-hardlinks source_local_repo dest_local_repo # clone a repository and copy object files instead of using hardlinks for local repo objects.


GIT SVN


Git svn is a tool that allows us to use git over a svn repo. It provides a bidirectional flow of changes between a Subversion and a git repository.

$ man git-svn

$ aptitude install git-svn

$ git svn init --stdlayout # Creates an empty repository for git svn using standard layout.
$ git svn fetch # Fetches unfetched revisions from remote svn repo.

Clones a remote svn repository:
svn equivalent command: $ svn checkout http://foo.bar.com
$ git svn clone --stdlayout http://foo.bar.com

To update local repository:
svn equivalent command: $ svn update
$ git svn rebase

To commit your changes to remote repo:
$ get svn dcommit

Git svn reference
Git - SVN Crash Course


SHOW LOGS


$ git log # shows general change log.
$ git log -8 # shows last 8 changes in the log.
$ git log file_name # shows change log for file_name.
$ git log branch_name # shows change log for that branch_name.
$ git log branch_name file_name # shows change log for that file_name in branch_name branch.


SHOW DIFFERENCES


$ git diff # shows changes between current files and latest commit.
$ git diff HEAD # Same as previous one.
$ git diff HEAD~1 # Shows differences between current files and previous to latest post.
$ git diff HEAD~2 HEAD~1 # Shows differences between one commit before last one and two commits before.
$ git diff commit_1 commit_2 # shows differences between commit_2 and commit_1. $ git log shows commit IDs.
It is not needed to write commit names entiretly, only first characters to match them unmistakably.

$ git diff branch_1 branch_2 # shows differences between HEAD in branch_1 and HEAD in branch_2.
$ git diff branch_1 branch_2 directory # shows differences for that directory between HEAD in branch_1 and HEAD in branch_2.


SEARCH FOR PATTERNS


Find lines matching foo.bar regular expression in current working directory and its subdirectories:
$ git grep -e foo.bar

Show also number of line for each match:
$ git grep -n -e foo.bar

Ignore the case in the regexp match:
$ git grep -n -i -e foo.bar

Match two expresions (boolean operators: or, and, not):
$ git grep -e foo --or -e bar
$ git grep -e foo --and --not -e bar

http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja/


STATUS


$ git status # shows the working tree status.


SHOW OBJECTS


$ git show tag_name # shows tag_name tag object.
$ git show HEAD # shows last commit.
$ git show HEAD~1 # shows previous to last commit.


LIST ALL FILES


$ git ls-files # list all files.


TAGS


$ git tag # List all tags

$ git show tag_name # Display info about a tag.

Create a lightweight tag:
$ git tag tag_name branch_name # Add a tag named tag_name into branch_name branch.

Create an annotated tag:
$ git tag -a tag_name -m "Message about this annotated tag."

Delete a tag in local repository:
$ git tag -d tag_name

Tags by default are not pushed to a remote repository, so we specifically push them:

$ git push origin --tags # Upload all tags to a remote repository.

$ git push origin tag_name # Upload a specific tag to remote repo.


Clone a specific tag from a remote:
$ git clone -b tag_name remote_repo


https://git-scm.com/book/en/v2/Git-Basics-Tagging



BRANCHES


$ git branch -r # show remote tracked branches
$ git branch # show local branches
$ git branch branch_name # it creates branch_name branch.

$ git checkout master # changes into master branch.
$ git checkout -b local_name remote_name # set up local_name branch to track remote branch remote_name.
E.g: $ git checkout -b directfb-1.4 origin/directfb-1.4

Create a branch starting from an old commit:
$ git branch new_branch_name old_commit_hash # Create new_branch_name branch from old_commit_hash but stay in current branch.
$ git checkout -b new_branch_name old_commit_hash # Create new_branch_name branch from old_commit_hash and switch to that branch.

List upstream branches (the ones they were cloned from: usually origin/blah):
$ git branch -vv

Make a local branch point to a remote branch
$ git branch --set-upstream-to=origin/my_remote_branch my_local_branch
or
$ git branch -u origin/my_remote_branch my_local_branch
Now when executing $ git pull it will get data from my_remote_branch into my_local_branch by default.


Delete a branch

$ git branch -d foo # delete foo branch.
If some of the commits of foo branch are not also in HEAD or in upstream branch it complains about:
error: The branch 'foo' is not fully merged.

and refuses to delete the branch.

To delete it anyway:
$ git branch -D foo

Git Pocket Guide: Deleting a Branch.


GIT CHECKOUT


$ git checkout branch_name # changes into branch_name branch.
$ git checkout file_name # recovers file_name file from HEAD index repo and restores it.
$ git checkout -b local_name remote_name # set up local_name branch to track remote branch remote_name.


ADD, MOVE AND DELETE FILES AND DIRECTORIES TO REPO INDEX


Add files

Add files and directories to repo index:
$ git add file_name # Adds file_name file to repo index.
$ git add directory_name # Adds a directory recursively to repo index.

Delete files

Delete a file from index and from local copy:
$ git rm file_name
Change still needs to be committed. File is not deleted from history.

Delete file from index without deleting your local file:
$ git rm --cached file_name

$ rm file_name # This command deletes a file but it does not delete it from index.

Move or rename files

Rename a file or directory:
$ git mv orig_file new_file

Move a file/directory inside an existing directory
$ git mv orig_file dest_dir

NOTE: After moving files or directories changes must still be committed (orig files and new files too).


SET AUTHOR'S NAME AND EMAIL


You should set name and email before any commit, because config changes will only affect future commits.
Existing commits will retain the info they were committed with.
There are two ways, setting environment variables or changing global config settings.

Setting environment variables
i.e: GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL
This will override git-config settings if they are defined.

$ alias git_commit_as_me='env
GIT_AUTHOR_EMAIL="me@foo.bar.net"
GIT_AUTHOR_NAME="My Name here" git commit'


When committing, i.e:
$ git_commit_as_me -m "whatever" -a


Changing global config settings:
This changes user email and name for all git repositories, saving config changes in ~/.gitconfig
$ git config --global user.name "Firstname Lastname"
$ git config --global user.email "my_email@foo.bar.com"

Then
$ git commit -m "whatever" -a
will commit your changes using your name and email address.


COMMITTING CHANGES


$ git commit -m "message for the commit." -a # commits all current changes into git repo.
$ git commit -m "message for the commit." file_name # commits current file_name changes.

$ git commit --amend # Change last commit. Usually it is used to change last commit message.
$ git commit --amend --author='Your Name <you@example.com>' # To change author in last commit.

PICK ONE COMMIT from another branch, remote repo, etc, and commit it to current repo branch.
$ git cherry-pick commit_id

If cherry-pick commit fails you can undo it:
$ git cherry-pick --abort

Cherry pick a range of commits:
$ git cherry-pick commit_a_hash..commit_b_hash
It cherry-picks from commit_a_hash to commit_b_hash.
(IMPORTANT: commit_a_hash is excluded from the cherry-pick)


DISABLE PAGER


$ git --no-pager diff # disable pager i.e. less when showing diff output.


GIT HELP


$ git help init # shows git help for git init command.
$ git help filter-branch # shows help about filter-branch
Same for every other git command.


GIT REMOTE


$ git remote # show all remote configurations for our repo.
$ git remote show origin # show information about origin remote.

$ git remote add remote_config_name url # add a remote configuration from url and names it remote_config_name.
$ git remote rm config_name # delete remote "config_name" repo from our repo configuration. All remote-tracking branches and configuration settings for the remote are removed.

$ git remote update # fetch all updates from remotes into our repo.


CLEANING


$ git clean -d -f # clean untracked files and directories.


SHOWS DIFFERENCE BETWEEN LOCAL AND REMOTE REPOS


$ git branch -r
$ git remote # shows remote repo name.
> origin
$ git fetch origin
$ git diff HEAD origin
or
$ git diff master origin/master


CHANGE SOMETHING IN A COMMIT


# Select one commit ahead from that commit.
$ git rebase -i HEAD~5
Change in editor "pick" into "edit" (be careful) for that parent commit.
# Perform changes here
i.e: $ git commit --amend
# After finished
$ git rebase --continue


DELETE COMMITS


# Delete last commit forever
$ git reset --hard HEAD~1

# Delete last commit but maintain its changes as uncommited.
$ git reset --soft HEAD~1
or
$ git reset HEAD~1

# Completely delete latest three commits.
$ git reset --hard HEAD~3


GET CHANGES FROM REMOTE


$ git fetch remote_name # or $ git fetch
$ git pull

$ git pull origin master # pull changes from remote master branch into current branch and merge them.

$ git pull origin foo:master # pull changes from foo branch in remote to master branch in local.


GET CHANGES FROM LOCAL REPOSITORY


$ git pull . edge:master # pull changes from local edge branch into local master branch.


CREATE AND APPLY PATCHES


$ git format-patch -1 # Create a patch for latest commit.

$ git format-patch -2 # Create two patches, for the two latest commits.

To apply a patch:
$ git am patch_name


REMOVE A DIRECTORY IN ALL COMMITS


$ git filter-branch --tree-filter 'test -d src && rm -rf src || echo "Nothing to do"' --force -- --all


DELETE ALL COMMITS WITH EMPTY CHANGE-SETS


$ git filter-branch --tree-filter '' --prune-empty --force -- --all


REBASE YOUR CHANGES IF SOMEONE HAS ALREADY SUBMITTED CHANGES TO REMOTE REPO


If you try to push your changes to a remote repository:
$ git push origin master:master
and it fails because someone already sent his changes and it does not match with your tree.

Then you could rebase your tree so your changes become at the top of his:
$ git pull --ff --rebase origin

This means download remote changes and execute git rebase, so your changes appear on the top of the tree.

Now you can push your changes safely:
$ git push origin master:master


GIT BLAME


Show info about last performed change (author, date, commit id) for each line in a tracked file.
$ git blame file_name


MERGE or CHERRY-PICK CONFLICT


If a merge or a cherry-pick fails because of a conflict.

You can reverse it:

Revert the merge:
$ git reset --merge

Reverse the cherry-pick:
$ git cherry-pick --abort

or

SOLVE MERGE/CHERRY-PICK CONFLICT

To show pending changes:
$ git diff

We find e.g: a file file.c with conflicting changes:
<<<<<
from old file
================
from new file
>>>>>


We edit those lines solving the conflict and erasing << === >>.

Then add the modified file to path:
$ git add file.c

And finish the commit:
$ git commit

Message and files are automatically added by git.


Resolving a merge


REFERENCE


$ man git
$ man git filter-branch
$ man git pull
$ man git-help # same as $ man git help
$ man git grep

Pro Git Book