The world's most advanced distributed version control system.
The git command is widely known. Linus Torvalds created the open-source Linux kernel in 1991, which has since grown into the largest server operating system software.
While Linus created Linux, its growth relied on volunteers worldwide. How was this code managed?
Before 2002, volunteers sent source code patches via diff to Linus, who merged them manually!
You might wonder why Linus didn't use a version control system. Free systems like CVS and SVN existed, but Linus strongly opposed them because they were slow and required an internet connection. Commercial systems were better but contradicted the open-source spirit of Linux.
By 2002, the codebase was too large for manual management. Linus chose a commercial system called BitKeeper, which the owner, BitMover, allowed the Linux community to use for free.
This arrangement broke down in 2005 when Andrew Tridgell (creator of Samba) attempted to reverse-engineer the BitKeeper protocol. BitMover revoked the free license.
Instead of apologizing, Linus spent two weeks writing his own distributed version control system in C: Git! Within a month, the Linux kernel source was managed by Git.
Git rapidly became the most popular distributed version control system, especially after GitHub launched in 2008, providing free Git hosting for open-source projects like jQuery, PHP, and Ruby.
If BitMover hadn't threatened the Linux community, we might not have the free and powerful Git we use today.
git [--version] [--help] [-C <path>] [-c name=value] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | --no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] <command> [<args>]
add Add file contents to the index
bisect Use binary search to find the commit that introduced a bug
branch List, create, or delete branches
checkout Check out a branch or paths to the working tree
clone Clone a repository into a new directory
commit Record changes to the repository
diff Show changes between commits, commit and working tree, etc.
fetch Download objects and refs from another repository
grep Print lines matching a pattern
init Create an empty Git repository or reinitialize an existing one
log Show commit logs
merge Join two or more development histories together
mv Move or rename a file, a directory, or a symlink
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
rebase Reapply commits on top of another base tip
reset Reset current HEAD to the specified state
rm Remove files from the working tree and from the index
show Show various types of objects
status Show the working tree status
tag Create, list, delete or verify a tag object signed with GPG
init
git init # Initialize
status
git status # Get status
add
git add file # . or * adds all
git rm --cached <added_file_to_undo> # Undo git add before commit
git reset head # Alternative to git rm --cached
commit
git commit -m "message"
remote
git remote add origin git@github.com:JSLite/test.git # Add remote origin
push
git push -u origin master # push and set upstream tracking
git push origin master
git push -f origin master # Force push
clone
git clone git://github.com/JSLite/JSLite.js.git
git clone git://github.com/JSLite/JSLite.js.git mypro # Clone to custom folder
git clone [user@]example.com:path/to/repo.git/ # SSH syntax
git clone <repository_url> <local_directory>
git clone http[s]://example.com/path/to/repo.git/
git clone ssh://example.com/path/to/repo.git/
git clone git://example.com/path/to/repo.git/
git clone /opt/git/project.git
git clone file:///opt/git/project.git
git clone ftp[s]://example.com/path/to/repo.git/
git clone rsync://example.com/path/to/repo.git/
Test account info with ssh -T git@github.com.
git help config # Get help
git config --global user.name "Your Name" # Modify global name
git config --global user.email "email@example.com" # Modify global email
git config --list # View configuration
Automatically convert CRLF to LF on commit:
git config --global core.autocrlf input
ssh-keygen -t rsa -C 'email@example.com' # Generate key
ssh-keygen -t rsa -C "email@example.com" -f ~/.ssh/my_rsa # Specify directory and filename
ssh -T git@github.com # Test connection
1. Generate named keys
ssh-keygen -t rsa -C "email" -f ~/.ssh/jslite_rsa
2. Copy key to platform
cat ~/.ssh/jslite_rsa.pub
3. Modify config file
vim ~/.ssh/config
Host jslite.github.com
HostName github.com
User git
IdentityFile ~/.ssh/jslite_rsa
Host work.github.com
HostName github.com
User git
IdentityFile ~/.ssh/work_rsa
4. Test
ssh -T git@jslite.github.com
ssh -T work.github.com
5. Usage
git clone git@jslite.github.com:username/learngit.git
git clone git@work.github.com:username/learngit.git
Note: If you rename id_rsa, add it to the SSH agent:
ssh-add ~/.ssh/jslite_rsa
ssh-add -l # List keys
ssh-add -D # Delete all keys
ssh-add -d ~/.ssh/jslite_rsa # Delete specific key
ssh-keygen -t rsa -P '' -f ~/.ssh/server.key
ssh-copy-id -i ~/.ssh/server.key.pub root@192.168.182.112
Edit ~/.ssh/config:
Host my_server
HostName 192.168.182.112
User root
PreferredAuthentications publickey
IdentityFile ~/.ssh/server.key
Login with ssh my_server.
Edit .git/config:
[remote "origin"]
- url = https://github.com/username/rep.git
+ url = https://username:password@github.com/username/rep.git
1. Add 3 remote URLs
git remote add origin https://github.com/JSLite/JSLite.git
git remote set-url --add origin https://gitlab.com/wang/JSLite.js.git
git remote set-url --add origin https://oschina.net/wang/JSLite.js.git
2. Delete a set-url
git remote set-url --delete origin https://oschina.net/wang/JSLite.js.git
3. Push code
git push origin master
4. Pull code
Only pulls from the first URL in origin.
git pull origin master
git pull --all # Fetch all including tags
Use -p to prune local branches that no longer exist on remote:
git pull -p
# Equivalent to:
git fetch --prune origin
git remote remove origin
git remote add origin git@github.com:username/repo.git
git reset --hard HEAD~1 # Revert one commit
git push -f origin HEAD:master # Sync to remote
git reset --hard FETCH_HEAD
If error occurs:
git checkout -b temp
git checkout master
git reset --hard # Discard staged and unstaged changes
git checkout . # Revert all changes, but don't delete new files
git clean -xdf # Delete untracked files
Using stash:
git stash && git stash drop
git revert HEAD~1 # Reverts the commit and creates a new commit
git push
git reset --hard <hash>
# --hard discards all local changes
# --soft keeps local changes
git checkout --orphan gh-pages
git rm -rf .
git rebase -i HEAD~4
# Change 'pick' to 'squash' (or 's') for commits to be squashed
git push -f origin master
git commit --amend # Modify last commit
git rebase -i HEAD~3 # Modify last 3 commits
# Change 'pick' to 'edit'
# Then:
git commit --amend
git rebase --continue
git push -f origin master
git remote add upstream https://github.com/original_owner/repo.git
git fetch upstream
git checkout master
git merge upstream/master
git filter-branch -f --env-filter '
OLD_EMAIL="old@example.com"
CORRECT_NAME="New Name"
CORRECT_EMAIL="new@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
Force push:
git push --force --tags origin 'refs/heads/*'
git log --pretty=oneline filename
git show <hash>
git blame filename
git config --global alias.st status
git config --global alias.br branch
git config --global alias.co checkout
git config --global alias.ci commit
git clone --recurse-submodules <url>
# Or manually:
git submodule add <url> <path>
git submodule init
git submodule update
Update all submodules:
git submodule foreach git pull origin master
git log --pretty=oneline
git log --graph --oneline --abbrev-commit
git reflog # History of all actions