Git
Git [1], is a distributed revision control and source code management (SCM) system with an emphasis on speed.
Initially designed and developed by Linus Torvalds for Linux kernel development, Git has since been adopted by many other projects.
Every Git working directory is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server.
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Git is easy to learn, which I sincerely doubt, and has a tiny footprint with lightning fast performance.
It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows.
Git is the de-facto-vcm.
Introduction
Many people from traditional VCS systems have trouble learning and especially knowing Git. See the why at Why the heck is Git so hard?.
So if you are still struggling with Git, try to do it over and over. This webpage may help you in doing so.
Stages
This is the main thing to remember about Git if you want the rest of your learning process to go smoothly.
This leads us to the three main sections and and two extra stages of a Git project:
Please take a close look at interactive Git-Cheat Sheet at NdpSoftware Git-CheatSheet. The example ScreenShot on the right is NOT interactive! |
Summerise
When your project is under the care of a VCS, you edit in your working directory and commit your changes to your repository for safekeeping.
Git works similarly but inserts another layer, the Index, between the working directory and the repository to stage, or collect, alterations.
When you manage your code with Git:
- You edit in your working directory,
- Accumulate changes in your index
- Commit whatever has amassed in the index as a single change-set.
Basic Workflow
The basic Git workflow goes something like this:
- Modify files in your working directory.
- Stage the files, adding snapshots of them to your staging area. In fact telling the repo you will commit the files into the local repository.
- Commit, which takes the files as they are in the staging area and stores that snapshot permanently to your Git directory (Local Repository).
- Push, which takes the committed files into the remote repo.
Setup
To setup git [2] follow the steps below.
Username
First you need to tell git your name, so that it can properly label the commits you make.
# Sets the default name for git to use when you commit. $ git config --global user.name "harm"
Git saves your email address into the commits you make. We use the email address to associate your commits with your GitHub [3][4] account.
# Sets the default email account for git when you commit $ git config --global user.email "h.frielink@<you-server-name>"
- Git global Config, More item on the global config of Git, i.e. the line endings.
Cheat Sheet
Always handy are Cheat Sheets [5].
Information & Config
Information | Tools | ||
---|---|---|---|
Status Repo | git status | Store away (stash) | git stash |
Shows git version | git --version | Configuration | git config |
Show files in index | git ls-files -s |
Creation, Addition & Removal
Create & Clone | Add & Remove | ||
---|---|---|---|
Initialized empty Git repository in .git/ | git init | Add changes to INDEX | git add <filename> |
Clone local repo | git clone /path | Add all changes to INDEX | git add * |
Clone remote repo | git clone username@host:/path/to/repo | Remove / Delete | git rm <filename> |
Connect local repo to remote repo | git remote add <remote-url> | Remove staged files (unstage) | git rm --cached <file>... |
Commit & Branches
Commit & Synchronize | Branches | ||
---|---|---|---|
Commit changes | git commit -m "Message" | Create new branch | git checkout -b <branch> i.e.: git checkout feature-x |
Push changes to remote repo | git push origin master | Switch to master branch | git checkout master |
Connect local repo to remote repo | git remote add origin <server> | Delete branch | git branch -d <branch> |
Update local repo with remote changes | git pull | push branch to remote repo | git push origin <branch> |
Merging & Tagging
Merge | Tagging | ||
---|---|---|---|
Merge changes from another branch | git merge <branch> | Create tag | git tag <tag> <commit-ID> |
View changes between 2 branches | git diff <src-branch> <trg-branch> | Get commit IDs | git log |
Usage gitignore
The .gitignore is a powerful method for skipping files from the VCS storage.
However if you have already stored a file into the VCS you need to remove it from the VCS, but not from the local filesystem.
Remove | gitignore | ||
---|---|---|---|
Remove VCS but keep local | git rm --cached <file-ext> | Check ignored file | git check-ignore -v <path/file> |
Please note for the global gitignore:
# Which and where is my global gitignore? $ git config --get core.excludesfile ~/.gitignore_global
Now you know which file is used. To set your own global gitignore.
$ git config --global core.excludesfile ~/.gitignore_global
Beginner Documentation
The beginners documentation is taken from the cheat sheets of Atlassian [6].
Basics
Git Command | Description |
---|---|
git init <directory> | Creates an empty Git repository in specified directory <directory>. Run without arguments to initialize the current directory as Git-Repository. |
git clone <repo> | Clones a repository located at <repo> onto the local machine. Original repository can be located on the local filesystem or on the remote machine via HTTP or SSH. |
git config user.name <name> | Defines author name to be used for all commits in the current repo. Developers commonly use --global flag to set config options for the current user. |
git add <directory> | Stages all changes in the <directory> for the next commit. Replace <directory> with <file> to change a specific file. |
git commit -m "<message>" | Commits the staged snapshot with given text-message "<message>". |
git status | Lists which files are staged, unstaged and untracked. |
git log | Displays the entire commit history using the default format. For customization see additional options. |
Undoing Changes
Git Command | Description |
---|---|
git revert <commit> | Creates new commit that undoes all the changes made in commit then apply it to the current branch. |
git reset <file> | Removes <file> from the staging area, but leaves the working directory unchanged. This unstages a file without any changes. |
git clean -n | Shows which files would be removed from the working directory. Use the -f flag in place of -n flag to execute the clean. |
Rewriting Git History
Git Command | Description |
---|---|
git commit --amend | Replaces the last commit with the staged changes and last commit combined. Use with nothing staged to edit the last commit’s message. |
git rebase <base> | Rebases the current branch onto <base>. <base> can be a commit ID, a branch name, a tag, or a relative reference to HEAD. |
git reflog | Shows a log of changes to the local repository’s HEAD. Add --relative-date flag to show date info or --all to show all refs. |
Git Branches
Git Command | Description |
---|---|
git branch | Lists all of the branches in your repo. Add a <branch> argument to create a new branch with the name <branch>. |
git checkout -b <branch> | Creates and checks out a new branch named <branch>. Drop the -b flag to checkout an existing branch. |
git merge <branch> | Merge <branch> into the current branch. |
Remote Repositories
Git Command | Description |
---|---|
git remote add <name> <branch> | Creates a new connection to a remote repo. After adding a remote, you can use <name> as a shortcut for <url> in other commands. |
git fetch <remote> <branch> | Fetches a specific <branch>, from the repo. Leave off <branch> to fetch all remote refs. |
git pull <remote> | Fetches the specified remote’s copy of current branch and immediately merge it into the local copy. |
git push <remote> <branch> | Pushes the branch to <remote>, along with necessary commits and objects. Creates named branch in the remote repo if it doesn’t exist. |
git config --get remote.origin.url | Gets the remote URL of the current repository. |
Git difference
Git Command | Description |
---|---|
git diff HEAD | Shows difference between working directory and last commit. |
git diff --cached | Shows difference between staged changes and last commit |
Git reset
Git Command | Description |
---|---|
git reset | Resets staging area to match most recent commit, but leaves the working directory unchanged. |
git reset --hard | Resets staging area and working directory to match most recent commit and overwrites all changes in the working directory. |
git reset <commit> | Moves the current branch tip backward to <commit>, resets the staging area to match, but leaves the working directory alone. |
git reset --hard <commit> | Same as previous, but resets both the staging area & working directory to match. Deletes uncommitted changes, and all commits after <commit>. |
Git rebase
Git Command | Description |
---|---|
git rebase -i <base> | Interactively rebases current branch onto <base>. Launches editor to enter commands for how each commit will be transferred to the new base. |
Scenarios's
New repo from scratch
Say you’ve just got some data from a collaborator and are about to start exploring it.
- Create a directory to contain the project.
- Go into the new directory.
$ git init
- Write some code.
$ git add .
to add the files (see the typical use page).$ git commit -m "Introduction"
.
The first file to create (and add and commit) is probably a ReadMe file, either as plain text or with Markdown, describing the project.
Markdown allows you to add a bit of text markup, like hyperlinks, bold/italics, or to indicate code with a monospace font.
Markdown is easily converted to html for viewing in a web browser, and GitHub will do this for you automatically.
A new repo from an existing project
Say you’ve got an existing project that you want to start tracking with git on GitLab [7]
Main | Additional Data |
---|---|
Assume:
Steps:
# Goto the directory containing the project (/Source/AWK) $ cd /Sources/AWK # It is very wise to create a .gitignore file and a README.md first! # Also if made, add to the .svn ignore! $ git init $ git remote add origin git@gitlab.com:HaFr1954/awk.git $ git add . $ git commit -m "Initial commit" xx files changed, xxxx insertions(*) ... $ git push -u origin master Counting objects xx, done, ... Branch 'master' set up track remote branch 'master' from 'origin'
$ git add .gitignore $ git commit -m "Introducing gitignore" Now open SourceTree. You need to add the project. Do:
Explanation: The git-directory contains the remote URL! See: the config file in the git-directory!
$ git rm -r --cached .svn And go to SourceTree to finalize by commit and push. On other devicesTo add the same repo on an already existing svn-repo on another device, the most simple way is:
$ rmdir /Data/AWK $ cd /Data/AWK $ git clone <url> .
|
Examples Git .ignore file
# Compiled source # ################### *.com *.class *.dll *.exe *.o *.so # Packages # ############ # it's better to unpack these files and commit the raw source # git has its own built in compression methods *.7z *.dmg *.gz *.iso *.jar *.rar *.tar *.zip # Version Control ################# .svn \#svn-prop.tmp# # Logs and databases # ###################### *.log *.sql *.sqlite # OS generated files # ###################### .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db la Template for README.md # Introduction Project _AWK_ contains .. The website has always been under VCS Subversion. It is my wish to migrate to Git, but for a while I want to use both Subversion and Git next to each other. It does not contain the directories for Subversion and the Log-directory and files. The main tools for the maintenance of the repository under Git are: - Git CLI - Atlassian Git Tool SourceTree. - Gitlab Webtool # Comments # Issues # Milestones # Version The current version is 0.1.0.1 - 24 Jan 2019 - Introduction ## Version History - 0.1.0.1 - 24 Jan 2019 - Introducing VCS Git # Explanation on Gitlab Markdown GitLab uses “GitLab Flavored Markdown” (GFM). It extends the CommonMark specification (which is based on standard Markdown) in a few significant ways to add additional useful functionality. It was inspired by GitHub Flavored Markdown. You can use GFM in the following areas: - Comments - Issues - Merge requests - Milestones - Snippets (the snippet must be named with a .md extension) - Wiki pages - Markdown documents inside repositories - Epics See: https://docs.gitlab.com/ee/user/markdown.html |
Problems
Diacritic Filenames
If you have filenames with diacritic characters (i.e. éíóúàèìòùãõ) and you are on OS X, you might have problems. After cloning these files maybe marked as unknown in subversion. Special for MAC:
$ git config --global core.precomposeunicode true
As described in git config man page, the option is related to the particular decomposition of Unicode characters in Mac OS:
This option is only used by Mac OS implementation of git.
When core.precomposeunicode=true, git reverts the unicode decomposition of filenames done by Mac OS.
This is useful when sharing a repository between Mac OS and Linux or Windows. (Git for Windows 1.7.10 or higher is needed, or git under cygwin 1.7).
When false, file names are handled fully transparent by git, which is backward compatible with older versions of git.
Connect it to GitLab
You’ve now got a local git repository.
You can use git locally, like that, if you want. But if you want the thing to have a home on github, do the following.
- Go to GitLab.
- Log in to your account.
- Click the wnew project button in the top-right.
You’ll have an option there to initialize the repository with:- ProjectName (Mandatory)
- Project Description (Optional)
- Visibility Level choose private
- Initialize with a README
- Click on the create button
- Click the “Create repository” button.
Now, follow the second set of instructions.
- On the GitLab go to your project
- Settings → Repository → Protected Branches"
- Do the required changes to the unprotect!
- Now perform
$ git push gitlab master --force
And you have it done!
Inside .git folder
What's inside the Git-Local-Repository directory .git? [9]
. |-- COMMIT_EDITMSG |-- FETCH_HEAD |-- HEAD |-- ORIG_HEAD |-- branches |-- config |-- description |-- hooks | |-- applypatch-msg | |-- commit-msg | |-- post-commit | |-- post-receive | |-- post-update | |-- pre-applypatch | |-- pre-commit | |-- pre-rebase | |-- prepare-commit-msg | `-- update |-- index |-- info | `-- exclude |-- logs | |-- HEAD | `-- refs |-- objects `-- refs |-- heads |-- remotes |-- stash `-- tags |
|
Git Tags
Although Git implements only one kind of tag object, there are two basic tag types, usually called
- Lightweight tags are simply references to a commit object and are usually considered private to a repository.
- Annotated tag is more substantial and creates an object. It contains a message, supplied by you.
Branches
A branch is the fundamental means of launching a separate line of development within a software project.
A branch is a split from a kind of unified, primal state, allowing development to continue in multiple directions simultaneously and, potentially, to produce different versions of the project.
Often, a branch is reconciled and merged with other branches to reunite disparate efforts.
Merge
The most difficult part of Git is merging, because it is complex and not very intuitive.
The process is complex because it has so many features / strategies.
- Git SCM Reference, Git Merge Strategies
Replace the master branch with another branch
If you checkout your current branch and merge the master into it with the ‘ours’ strategy, it has the effect of absorbing the master into your current branch but not using anything of the master.
This way, when you checkout the master and do an ordinary fast forward merge of your feature branch, the merge commit will be exactly like your feature branch, effectively making it seem like you replaced the master with your feature branch.
$ git checkout feature_branch $ git merge -s ours --no-commit master $ git commit # Add a message regarding the replacement that you just did $ git checkout master $ git merge feature_branch
1. Makes sure you have the correct version
2. The 'ours' strategy resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. Keeps the content of this branch, but record a merge
3. Merging ours and does nothing with the master.
4. Checking out the new master
5. Fast-Forward master up to the merge
But the best answer is quite simple:
# Makes sure everything is pushed up to your remote repository $ git checkout master # Overwrites "master" with "better_branch" $ git reset --hard better_branch # Forces the push to your remote repository $ git push -f origin master
Please note to perform the command
$ git reset --hard origin/master
On every other local copy of the repository.
- StackOverflow, Make the current git branch a master
Gui Sourcetree
Atlassian Sourcetree is a GUI Git Client implementing the following git-commands to make your life easier.
Git Commit
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree commit -q -F /var/folders/.../SourceTreeTemp.d2GNL8 -a
Git CLI Parameter | Description |
---|---|
-c name=value | Pass a configuration parameter to the command. The value given will override values from configuration files. The <name> is expected in the same format as listed by git config (subkeys separated by dots). |
-q --quiet |
Suppress commit summary message. |
-F <file-name> | Take the commit message from the given file. Use - to read the message from the standard input. |
-a | Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected. |
Git push
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree push -v --tags origin refs/heads/master:refs/heads/master
Git CLI Parameter | Description |
---|---|
-c name=value | Pass a configuration parameter to the command. The value given will override values from configuration files. The <name> is expected in the same format as listed by git config (subkeys separated by dots). |
-v --verbose |
Run verbosely. |
--tags | All refs under refs/tags are pushed, in addition to refspecs explicitly listed on the command line. |
Git pull
Sourcetree has implemented the pull in a 2-step operation:
- fetch
- pull.
Explanation: See the discussion on StackOverflow difference origin and master.
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree fetch origin
Git CLI Parameter | Description |
---|---|
-c name=value | Pass a configuration parameter to the command. The value given will override values from configuration files. The <name> is expected in the same format as listed by git config (subkeys separated by dots). |
fetch <repository> | Download objects and refs from another repository. It does not merge them! Please note that origin is the repository. |
The second operation is the pull command.
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree pull origin master
Git CLI Parameter | Description |
---|---|
-c name=value | Pass a configuration parameter to the command. The value given will override values from configuration files. The <name> is expected in the same format as listed by git config (subkeys separated by dots). |
pull <repository> <branch> | Fetches from and integrates with another repository or a local branch. Please note that origin refers to the repository and master to the local branch. |
Git tag
To mark a release or create a new release use the git -tagging option.
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree tag -a -m Beta-3-Bootgrid-3-Release
After the tagging the command needs to be pushed.
Git CLI Parameter | Description |
---|---|
-c name=value | Pass a configuration parameter to the command. The value given will override values from configuration files. The <name> is expected in the same format as listed by git config (subkeys separated by dots). |
tag | Creates, lists, deletes or verifies a tag object signed with GPG. |
-a | Makes an unsigned, annotated tag object. You may also use -s which makes a GPG-signed tag, using the default e-mail address’s key. |
-m | Uses the given tag message (instead of prompting). |
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree push -v origin refs/tags/Beta-3-Bootgrid-3-Release
See Push above.
Retrieving a specific tagged version
To retrieve a tagged version, do
# Retrieving the whole cloned local repository $ git clone # Retrieving the whole cloned remote repository $ git clone git@gitlab.com:<username>/<repo-name>.git # After the clone, list the tags: $ git tag -l # Checkout a specific tag: $ git checkout tags/<tag_name> -b <branch_name>
Git create Branch
$ git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree branch Bootgrid-4 $ git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree checkout Bootgrid-4 Switched to branch 'Bootgrid-4' $ git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree submodule update --init
Gitconfig
[credential] helper = osxkeychain [commit] template = /Users/frielink1/.stCommitMsg [core] excludesfile = /Users/frielink1/.gitignore_global precomposeunicode = true [diff] tool = bc3 [difftool "sourcetree"] cmd = /usr/local/bin/bcomp -ro $LOCAL $REMOTE path = [filter "lfs"] clean = git-lfs clean -- %f smudge = git-lfs smudge -- %f process = git-lfs filter-process required = true [merge] tool = sublimerge [mergetool "sublimerge"] cmd = subl -n --wait \"$REMOTE\" \"$BASE\" \"$LOCAL\" \"$MERGED\" --command \"sublimerge_diff_views\" trustExitCode = false [user] name = Harm Frielink email = harm@harmfrielink.nl
# To get the remote name http name. $ git config --get remote.origin.url git@gitlab.com:HaFr1954/java.git
See also
External
- GitHub is the best place to share code with friends, co-workers, classmates, and complete strangers. Over eight million people use GitHub to build amazing things together.
- Guides GitHub, Basic Information (Guides) to Git and the implementation of Git on GitHub.
- Help GitHub, The best place to look with a massive number of categories and help. A must if you are looking for something.
- Cloudforge, Free Git repository Website for all your code.
- Github, Caching your github password in git.
Internal
- CloudForge, vcs host.
- Git FAQ, FAQ on Git.
- GitHub, information on the GitBub, How to use, How to get information and more.
- Co-Existence Subversion & Git, is it possible to have to CVS repositories next to each other?
- Subversion & Git Repositories is a Private Webpage on using Git and Subversion together (co-existence).
- SourceTree, Atlassian Git Tool
Tutorials
- Atlassian, Git Tutorials.
- Tutorial, Introduction to git 1.5.1. or newer.
- Read-Write, Github for beginners.
- kbroman, Github Tutorial Init, how to start with git.
Tutorial Git
- Tutorial Git Add, Tutorial on the add function of Git.
- Tutorial Git Branch, Tutorial on the branch function of Git.
Reference
- ↑ Wikipedia Git-description, Git Software
- ↑ help-github, Setup.
- ↑ GitHub.com, Git-Repository Website for Open Source Projects
- ↑ GitHub, Help, Guides and more on using GitHub.
- ↑ Roger Dudler, Sheet Cheat
- ↑ Atlassian Git, Cheat Sheets.
- ↑ Co-Existence Subversion & Git, is an indept analysis of the coexistence of Subversion and Git and may also explain strange differences using to 2 together.
- ↑ StackOverflow, Remove a file/folder from a git repo without deleting it from the local filesystem.
- ↑ GitReady.com, What's inside your git-directory
- ↑ SHA: Git uses a common cryptographic hash function, called Secure Hash Function (SHA1), to name and identify objects within its database. Though perhaps not absolute, in practice it has proven to be solid enough to ensure integrity and trust for all Git’s distributed repositories. Git users speak of SHA1, hash code, and sometimes object ID interchangeably.