Git is a software source code "Change Management" (CM) system for collaborative development. It maintains a history of file versions. Unlike typical client-server CM systems which "check-out" the latest or a particular version of the files, Git is a distributed CM system where the user has a local copy (a clone) of the entire repository which includes the entire history of all files. The user working with files in their local project work area, interacts with the local clone repository, adding, editing and deleting files and eventually committing their changes. The user can then share these changes to the local repository with a "push" or "pull" to other Git repositories including a server based central "origin" repository.
Git command summary cheat sheet:
Command | Description | Man Page |
---|---|---|
git --help | List Git commands | git |
git --help command | Help on given "command" | git help |
git add path/filename
git add file1 file2 file3
|
Add a file or directory to Git CM control. This does not commit the files to the repository but merely adds files to "staging" status. Must also perform: git commit to enter changes in the repository. View staged files: git ls-files --stage Empty directories are not added. Git manages files only. --update: stage all tracked and modified files. Undo an add: git reset HEAD path/filename |
git add |
git blame filename | Show file line numbers annotated with author information. Also see git log | git blame |
git branch -a | List all branches (remote and local) | git branch |
git checkout parentPath/filename git checkout master git checkout e3b43d63 |
Undo local changes. Revert changes. This directive is misleading as it implies a client-server action. Instead, it relies on the local repo and sets the working copy to the unchanged version, reverting changes.
Checkout "master" will set the local work area to match the master branch. You can also specify the commit to which you want the local repo to view. Also see git reset |
git checkout |
git clean -df
git clean -df git -n clean git -dn clean |
Remove files not managed by Git.
-df: All unchecked files and directories are removed. -n: Dry run. Command not executed. -d: directories Clean has nothing to do with an Ant target of "clean" and is in no way related. Also see git gc |
git clean |
git clone http://git.megacorp.com/git/repo/projectx.git git clone ssh://user@git.megacorp.com:/srv/git/repo/projectx.git |
Copy/clone/create a local repository from the remote repository specified.
[Potential Pitfall]: The following error often is a connectivity issue: fatal: http://git.megacorp.com/git/repo/projectx.git/info/refs not valid: is this a git repository? If a proxy error is keeping you from connecting. Fix: unset http_proxy |
git clone |
git commit git commit dir-path/filename git commit -m "Message goes here." filename |
Check-in (commit) local staged "working" files into local repository. Files must be staged for commit using git add Files are recursively located and committed into the local git repository. Git commits are Atomic, i.e. all files are committed or none are committed, no incomplete check-in. | git commit |
git config --global user.name "John Doe" git config --global user.email jdoe@megacorp.com git config -l git config --global --unset user.password |
This configures ~/.gitconfig Show your local GIT configuration for your local repo Clear cached password. Will be prompted on next push/pull.[Potential Pitfall]: Error: fatal: Authentication failed for 'http://git.megacorp.com/git/repo/projectx.git/’ Fix: "git config --global --unset user.password" to clear passord cache. |
git config |
git diff
git diff e3b43d63 60fdba79 directory/path |
Show file diffs between the working tree and local repo.
Show file diffs between two commits. |
git diff |
git gc | Cleanup unnecessary files and optimize/compress local repo. | git gc |
git log
git log --oneline git log directory/path/file git log --author="name" git log --graph --decorate --oneline |
Show the Git log messages.
--oneline: brief description --graph --decorate: display branching like gitk except for text terminals. Note that the letter "q" will quit pagination mode. |
git log |
git ls-files --stage
git ls-files --cached git ls-files --modified git ls-files --others git ls-files --deleted git ls-files --unmerged git ls-files --killed ... |
List files staged.
List cached files. List modified files. List other (un-tracked) files. List deleted files. List un-merged files. List killed files that need to be removed due to file/directory conflicts for checkout-index to succeed. |
git ls-files |
git ls-remote -h http://domain/git/repo/projectx.git HEAD | List files under Git control on remote Git server. | git ls-remote |
git merge branch-name git merge --abort |
Merge a specified branch into your current branch you are in. If you are in the "master" branch, then "branch-name" will be merged into "master".
--abort: After starting a merge, you might want to stop the merge and return everything to its pre-merge state. --stat: Show a diffstat after merge completion -m: Message to be included in the merge commit |
git merge |
git mv file-old-name file-new-name | Rename a file. Moves/renames file. | git mv |
git mergetool | View file conflicts in a merge tool. Default is vimdiff
Assign a GUI tool: KDiff3:
Meld:
|
git mergetool |
git pull origin master | Update your local repo and working files with changes posted on the git remote server origin: refers to repository from which you will receive updates master: refers to the master branch from which you will receive updates This command is the same as performing the following two commands: git fetch git merge |
git pull |
git push origin master | Update the remote repo from the staged (identified with "git add") local working files origin: refers to repository from which you will receive updates master: refers to the master branch from which you will receive updates This command is the same as performing the following two commands: git fetch git merge |
git pull |
git remote -v | Show URL to origin server. | git remote |
git reset HEAD^ path/filename
git reset HEAD~1 path/filename git reset --hard HEAD^ path/filename |
Remove from staging (local copy of files still modified)
--hard: Don't keep changes, remove modifications to files. HEAD^: latest commit notation for Linux and bash shell terminals. HEAD~1: latest commit notation for Microsoft CMD shell. Microsoft DOS shell does not support "^".
Reset the repo to the last good commit specified and ignoring everything after e3b43d63:
|
git reset |
git revert HEAD | Not a commit undo but overwrites the commit with a new commit to reverse changes. Usually better to use "git reset --hard HEAD^ path/filename" when you want to abort your changes to a file. If you are trying to get back to a previously committed state, just use git checkout e3b43d63 | git revert |
git rm filename git rm -r directory/path |
Delete file from local working index. Don't use the UNIX command rm file-name. Must perform a "git commit" to update the repository.
-n: dry run -r: recursive removal when given a directory name. |
git rm |
git status | Show tracked files which have been staged, committed, etc. | git status |
git tag -a April_Sprint -m "Source used for April sprint demo" git tag -a April_Sprint -m "Source used for April sprint demo" e3b43d63 |
Add a "tag" to the commit to identify it in human readable terms. You can then push using the following: git push origin master April_Sprint or git push origin master --tags -a: Generate an annotated tag object. -d: Delete existing tags with the given names. -f: Replace an existing tag with the given name. -m: Add a message. |
git tag |
Where Commit is:
- HEAD: The latest revision in the repository.
- HEAD^: latest commit notation for Linux and bash shell terminals.
- HEAD~1: latest commit notation for Microsoft CMD shell. Microsoft DOS shell does not support "^".
- BASE: The "pristine" revision of an item in a working copy. Matches checked out version before any modifications.
- COMMITTED: The last revision in which an item changed before (or at) BASE.
- PREV: The revision just before the last revision in which an item changed. (Technically, COMMITTED - 1.)
Example Session:
(Assumes that the repository has already been created. For Git repository creation and Git server configuration, see the YoLinux Git server tutorial)- Checkout: git clone ssh://user@git.megacorp.com:/srv/git/repo/projectx.git
copy origin repository and create a local repository. - Go to source code directory: cd Projectx/src/main/java/com/megacorp/projectx
- Edit files:
- vi file1.java
- vi file2.java
- Verify and test: ant
We are ready to check-in the files into the Git repository. - Flag files as staged: git add file1.java file2.java
- Show status including files staged: git status
- After many long hours of editing and work, get updates others have made and merge changes with local working files: git pull origin master
- Resolve merge conflicts if they exist: git mergetool
At this point, a commit will fail until the merge is resolved. - Merge options:
- Decide on changes you want: git mergetool
Uses merge tool you specify. Default: vimdiff - Choose your file changes: git checkout --ours file1.java
(--ours: your file in your local work area) - Choose their file changes: git checkout --theirs file1.java
(--theirs: branch you are merging into. The file from remote origin server) - Edit the file to remove conflicts: vim file1.java
(the file will have >>>>>>> and <<<<<<< entries in it) - Throw out your changes/abort: git revert HEAD^
No resolve or check-in necessary if file is reverted.
- Decide on changes you want: git mergetool
- Commit to your local copy of repo: git commit -m "Commit message goes here"
- Verify and test, again: ant
There are many files and directories one would like git to ignore and never check-in to the repository. When programming C/C++ one may never want to check-in object (.o) files. Java programmers may never want to check-in ".class" files. IDE's like Netbeans will generate personal configuration settings that one would not want to check-in as they would always conflict with other developers. Git can be configured to ignore these files by generating the file .gitignore in the top directory of your repository.
Example src/projectx.git/.gitignore*.a *.o *.so *.dll *.lib a.out *.jar *.class
Add the following for Netbeans developers:
private.* /**/nbproject/private/
- git --global http.proxy http://proxy.megacorp.com:80
or - export HTTP_PROXY=proxy.megacorp.com:80
Since the dawn of source code management, change management (CM) systems have supported the notion of enforcing "properties" such as filtering carriage returns (^M), permissions, etc.
This is especially important for cross platform development as Microsoft development tools will often append a line with CRLF while non-Microsoft tool will typically terminate a line with only a LF. Files edited with Microsoft tools will have a CR which will be displayed as a "^M" with other tools. This may generate unnecessary merge conflicts, ridiculous git diff results, unecessary check-ins due to erroneous git status results and developer hostilities.
The line termination is defined for the entire Git repository by core.autocrlf
This can be set on the server repo:cd /srv/git/projectx.git/ git config core.autocrlf falseThis will set the server configuration file /srv/git/projectx.git/config
[core] repositoryformatversion = 0 filemode = true bare = true sharedrepository = 1 autocrlf = false [receive] denyNonFastforwards = true ... ..
or by command:
- git config core.sharedrepository 1
makes everything group readable and writable - git config receive.denyNonFastforwards true
makes sure that merges can't happen when you push to the repo. You have to do the merges on your local machine, and then push the result.
See the YoLinux.com GIT Server configuration tutorial for more on setting up a Git server.
The line termination rules can be overriden using the .gitattributes file (check-in to your repo in the top directory):# Auto detect text files and perform LF normalization * text=auto eol=lf *.cpp text diff=cpp eol=lf *.cs text diff=csharp eol=lf *.vcproj eol=crlf *.java text diff=java eol=lf *.html text diff=html eol=lf *.css text eol=lf *.js text eol=lf *.php text diff=php eol=lf *.module text diff=php eol=lf *.engine text diff=php eol=lf *.inc text diff=php eol=lf *.sql text eol=lf *.jpg binary diff=exif *.gif binary diff=exif *.png binary diff=exif *.csproj text merge=union *.sln text merge=union eol=crlf *.docx diff=word # relative paths are treated relative to the .gitattributes folder relative/path/*.txt text eol=lf
- This configuration "auto detects" text files and also defines C++ files (*.ccp), Java source (*.java), etc as text files.
- Visual Studio solution files (*.sln) maintain their Microsoft carriage return (cr) followed by a line feed (lf).
- diff: specifies the git filter to use when viewing a diff that contains changes.
- exif: Converts binary to a textural representation using exiftool to detect if changes have occurred.
Configure repo: git config diff.exif.textconv exiftool
- exif: Converts binary to a textural representation using exiftool to detect if changes have occurred.
- eol: End Of Line marked by:
- lf: Unix, Linux, standards based OS, proprietary legacy systems, etc.
- crlf: DOS and Microsoft OSs
- cr: Response input scripts, etc
- merge: Use the option "merge=union" when the solution to merge conflicts are to take lines from both versions, instead of leaving conflict chevron markers.
One can also specify "-merge" (the opposite, don't merge conflicted lines).
To "normalize" Java source files to LF terminated lines: find ./ -name "*.java" -exec dos2unix {} \;
Files may be marked as having execute permissions by doing the following:
git add script.sh git update-index --chmod=+x script.sh git commit -m "Add script"Note that an improper core.fileMode configuration can change the utility of this action. When set to false, the executable bit differences between the index and the working copy are ignored. Conversely, when set to true, file mode permission changes are considered changes.
CM systems such as RCS, CVS and Subversion have all supported tag substitutions and so can Git. Keywords are substituted and will not appear in the file until a new revision of the file is updated from the repository.
The following RCS attribute tags can be set on files stored in GIT. The keyword expansion of the following tags are substituted by a "smudge" filter upon a pull and a "clean" filter on a push. Download the smudge and clean filters.
The following are the supported tags which can be embedded into your source code:
RCS Tag | Expanded String |
---|---|
$Date$ | The date as provided by the shell command "date" $Date: Sun Jul 30 17:21:43 2017 -0700 $ |
$Author$ | Will provide the author's name as specified by ~/.gitconfig from the commands:
|
$Revision$ | This fills in the Git hash for the commit associated with this revision. $Revision: 93c4a4a5b871f3183ea90f7df159cc3e363ec534 $ |
$Source$ | File name |
$File$ | File name (same as $Source$) |
$Id$ | A summary of the previous 3 keywords: $File, $Date and $Author. |
Example source file comment:
/** $Revision$ $Author$ $Date$ $Source$ $File$ $Id$ */Expanded comment:
/** $Revision: 93c4a4a5b871f3183ea90f7df159cc3e363ec534 $ $Author: John Doe <john.doe@megacorp.com> $ $Date: Sun Jul 30 17:21:43 2017 -0700 $ $Source: filename.java $ $File: filename.java $ $Id: filename.java | Sun Jul 30 17:21:43 2017 -0700 | John Doe $ */
The personal configuration file ~/.gitconfig is where the filters are assigned. Add the following:
[filter "rcs-keywords"] clean = .git_filters/rcs-keywords.clean smudge = .git_filters/rcs-keywords.smudge %f
Place the .gitattributes file and .git_filters/ directory at the root of the CM directory tree:
File: projectx/.gitattributes*.h filter=rcs-keywords *.c filter=rcs-keywords *.cc filter=rcs-keywords *.cpp filter=rcs-keywords *.m filter=rcs-keywords *.mm filter=rcs-keywords *.java filter=rcs-keywords
Copy the filters to: Allow filters to be executed: chmod ugo+x projectx/.git_filters/rcs-keywords.smudge projectx/.git_filters/rcs-keywords.clean
Otherwise you will get the following error:
fatal: cannot exec '.git_filters/rcs-keywords.clean': Permission denied error: cannot fork to run external filter .git_filters/rcs-keywords.clean error: external filter .git_filters/rcs-keywords.clean failed
The filters are checked-in to Git and thus need to have a Git execute attribute applied: git update-index --chmod=+x projectx/.git_filters/rcs-keywords.smudge projectx/.git_filters/rcs-keywords.clean
Note that this tag substitution occurs on a fresh "git clone" or on a "git pull" and modifies the files in your workspace but does not affect the files in the repository itself. The author of the RCS tag edits will not see the substitutions unit they perform a fresh "git clone" to generate a new local repository or when a "git pull" finds file modifications and performs an update.
Three types of file differences are covered in this section:
- Show file differences made since a pull or checkout was made. This shows the changes you have made. It is useful to perform this before a commit.
- Show file differences between two files versions stored in Git.
- Show differences / conflicts, choose and merge.
Note that the following conventions are used:
- LOCAL: file on your current local branch
- REMOTE: branch you are merging to (e.g. new_branch you are trying to pull. Their changes.)
- MERGED: the partially merged file with merge conflicts marked with chevrons:
- <<<< HEAD : conflicted lines between this and "=====" are your changes
- >>>> 7c10716976ee3e9d49f69d71ec6cc4bd43957ec8 : conflicted lines between this and "=====" are their changes in the repository which conflict.
- BASE: the original common ancestor file from which LOCAL and REMOTE evolved. The file before the conflicted changes.
Git uses the command line Linux "diff" command. A GUI diff tool is far more intuitive and can be specified using the following commands:
- Configure git to use a GUI diff tool:
- git config --global diff.tool meld
- git config --global difftool.meld.cmd 'meld $LOCAL $REMOTE'
[diff] tool = meld [difftool "meld"] cmd = meld $LOCAL $REMOTE
- GUI diff between file in working area and repo: git difftool filename.java
Viewing (1/1): 'filename.java' Launch 'meld' [Y/n]: y
- View the differences for a file and two commits back: git difftool HEAD HEAD^^ filename.java
- View the differences for a file between two commits: git difftool a1a1c14299049c5e1cf60f8cc02f41bbf7d8b85f 93c4a4a5b871f3183ea90f7df159cc3e363ec534 filename.java
(Use "git log" to view the commit hashes) - View the differences for two files between two commits: git difftool a1a1c14299049c5e1cf60f8cc02f41bbf7d8b85f:file1.java 93c4a4a5b871f3183ea90f7df159cc3e363ec534:file2.java
- View all differences between two commits: git difftool a1a1c14299049c5e1cf60f8cc02f41bbf7d8b85f 93c4a4a5b871f3183ea90f7df159cc3e363ec534
Viewing (1/3): 'file_1.java' Launch 'meld' [Y/n]: y Viewing (2/3): 'file_2.java' Launch 'meld' [Y/n]: y Viewing (3/3): 'file_3.java' Launch 'meld' [Y/n]: y
Configure git to use a GUI merge tool. Note that most diff tools also support merges:
- git config --global merge.tool meld
- git config --global mergetool.meld.cmd 'meld $LOCAL $MERGED $REMOTE'
[merge] tool = meld [mergetool "meld"] cmd = meld $BASE $LOCAL $REMOTE --output $MERGED
Merge conflicts occur when two developers check out common files and both edit the same line/lines. Edits to different lines merge automatically and cleanly. When changes are made to the same line and then one developer commits and pushes the code, the second developer must deal with the merge conflicts by selecting the line they want, "ours" or "theirs". GUI merge tools support the management of a merge by addressing the lines marked as a conflict using the text markers ">>>>".
- tkdiff: [download]
- gtkdiff: Has diff3 and merge features. Written with GTK+. After gtkdiff-0.8.0, GNOME desktop required.
- diffUse: Diff/merge GUI tool. Good line matching features. Supports Unicode.
- kdiff3: Graphical directory and file diff, merge and edit. KDE3/Qt based. (Cross platform) MS/Windows download available. A very good directory and file diff and merge tool.
- Diff:
- git config --global diff.tool kdiff3
- git config --global difftool.kdiff3.cmd 'kdiff3 $LOCAL $REMOTE'
This adds the following entry to your ~/.gitconfig[diff] tool = kdiff3 [difftool "kdiff3"] cmd = kdiff3 $LOCAL $REMOTE
- Merge:
- git config --global merge.tool kdiff3
- git config --global mergetool.kdiff3.cmd 'kdiff3 $BASE $LOCAL $REMOTE -o $MERGED'
This adds the following entry to your ~/.gitconfig[merge] tool = kdiff3 [mergetool "kdiff3"] cmd = kdiff3 $LOCAL $BASE $REMOTE -o $MERGED
- Diff:
- Kompare: Ships with (RHEL6/RHEL5/RHEL4/FC3+) KDE SDK. [manual]
Included in Red Hat RPM package "kdesdk" an Ubuntu package "kompare".
[Potential Pitfall]: RPM installation error:error: Failed dependencies: perl(DCOP) is needed by kdesdk-3.5.4-3.el5.i386
Solution: Install the dependency package "kdebindings". - mgdiff: Motif-based graphical file difference browser and merge. Comes with S.u.S.E. distro.
- Meld: Compare, edit and merge.
- Diff:
- git config --global diff.tool meld
- git config --global difftool.meld.cmd 'meld $LOCAL $REMOTE'
This adds the following entry to your ~/.gitconfig[diff] tool = meld [difftool "meld"] cmd = meld $LOCAL $REMOTE
- Merge:
- git config --global merge.tool meld
- git config --global mergetool.meld.cmd 'meld $BASE $LOCAL $REMOTE --output $MERGED'
This adds the following entry to your ~/.gitconfig[merge] tool = meld [mergetool "meld"] cmd = meld $LOCAL $BASE $REMOTE --output $MERGED
- Diff:
- xxdiff: Compare 2 or 3 files and merge. Also compares directories.
- gvim and gvimdiff
- Beyond Compare - commercial tool (cross platform)
Git comes with a GUI: git gui and a browser tool gitk
The latest version is available from github.com: gitk
Installation:
- Ubuntu: sudo apt-get install git-gui
- From source:
- wget https://github.com/gitster/git/blob/master/gitk-git/gitk
- chmod +x gitk
For other options see:
- CollabNet: GitEye: cross platform, push/pull, history, diffs, revert, stash, etc. Intuitive and customizable
- SmartGit: cross platform commercial product
- QGit: View revisions, diffs, files history, files annotation, archive tree, Commit changes visually cherry picking modified files.
- Axosoft: GitKraken: commercial product. Free for non-commercial use. Cross platform.
- Git-cola: Python git front-end. (cross platform)
- GNOME: Giggle: GTK+ application
- GNOME: gitg
Web Clients:
- GitWeb: comes with Git
- GitLab: Ruby, community edition
- Gogs: written in Go
- Gitea: a fork of Gogs
- RhodeCode: community edition and commercial product. User control, permissions, code reviews, and tool integration.
- Gitssh2: Symfony PHP framework. Connects to repositories via ssh
- Axosoft: GitKraken:
- GitList:
- Kallithea: community edition
Plug-ins:
- nautilus-git: GNOME Nautilus/Nemo file browser GIT plug-in.
- EGit Eclipse IDE plug-in
- ALWAYS compile and test before pushing source code to the origin server. Developers expect shared changes to compile.
- Always add commit comments. Nothing is more obnoxious that looking at an uninformative log or information history.
- Monstrous binary files like CD or DVD ISO images are better suited for storage on a file system rather than in Git. Git will not be able to show differences between version and will be slower than a raw filesystem.
- Don't copy, rename and move directories and files with system shell commands. Use Git commands to "rm", "mv", and "add" files and then commit changes when done. Work within Git.
- Push changes as a single logical change-set for one purpose. Thus all code changes for a single bug fix or enhancement should be checked-in together.
This allows one to better follow the history log of changes.
- Stage code at the directory level and all changed files, recursively in the directory and sub-directories will be checked in together.
git add -all - Stage files together by specifying them explicitly:
git add file.cpp file2.cpp ...
- Stage code at the directory level and all changed files, recursively in the directory and sub-directories will be checked in together.
- Tie Bug tracking and Git CM together:
- Use comments when commiting files into Git. Add bug tracking numbers to the comments so Git will reference Trac bugs.
- If using Trac, add Trac comments so that links are generated to the Git repository by placing the Git revision hash in square braces (i.e. [e3b43d63]) in a Trac comment. In this way, Trac will have a direct URL link to Gitweb.
- If using Trac integrated with Git, refer to the Trac ticket in the Git commit comment using a "#" in front of the Trac ticket number (e.g. #65) This generates a hyperlink when the Git logs are viewed in Trac.
- Documentation and related artifacts checked-in to Git should not be under the source tree but parallel to it. This isolates the source tree so that email notification triggers sent to developers upon source changes will only go out on source changes or regression build and test systems like Jenkins or Cabie will only rebuild and test on source changes rather than on unrelated documentation changes.
Using Eclipse IDE with Git:
Block Eclipse from viewing the hidden ".Git/" directory so that Eclipse does not intrude or alter their contents:- Select the toolbar options: "Project" + "Properties"
- Select the "Java Build Path" + select the "Source" tab
- Select the "Excluded" item and select "Edit"
- In the lower half under "Exclusion patterns:" select "Add..." and enter the pattern **/.git/*
- YoLinux Tutorial: Git Server - Installation and Configuration
- YoLinux Tutorial: Git and Trac Server Installation and Configuration
- Git Home Page