Git

git is a version control system for tracking changes in source code during software development processes.

Getting Started

Create a Repository

Create a new local repository

$ git init [project name]

Clone a repository

$ git clone git_url

Clone a repository into a specified directory

$ git clone git_url my_directory

Make a change

Show modified files in working directory, staged for your next commit

$ git status

Stages the file, ready for commit

$ git add [file]

Stage all changed files, ready for commit

$ git add .

Commit all staged files to versioned history

$ git commit -m "commit message"

Commit all your tracked files to versioned history

$ git commit -am "commit message"

Unstages file, keeping the file changes

$ git reset [file]

Revert everything to the last commit

$ git reset --hard

Diff of what is changed but not staged

$ git diff

Diff of what is staged but not yet commited

$ git diff --staged

Apply any commits of current branch ahead of specified one

$ git rebase [branch]

Configuration

Set the name that will be attached to your commits and tags

$ git config --global user.name "name"

Set an email address that will be attached to your commits and tags

$ git config --global user.email "email"

Enable some colorization of Git output

$ git config --global color.ui auto

Edit the global configuration file in a text editor

$ git config --global --edit

Working with Branches

List all local branches

$ git branch

List all branches, local and remote

$ git branch -av

Switch to a branch, my_branch, and update working directory

$ git checkout my_branch

Create a new branch called new_branch

$ git branch new_branch

Delete the branch called my_branch

$ git branch -d my_branch

Merge branchA into branchB

$ git checkout branchB 
$ git merge branchA

Tag the current commit

$ git tag my_tag

Observe your Repository

Show the commit history for the currently active branch

$ git log

Show the commits on branchA that are not on branchB

$ git log branchB..branchA

Show the commits that changed file, even across renames

$ git log --follow [file]

Show the diff of what is in branchA that is not in branchB

$ git diff branchB...branchA

Show any object in Git in human-readable format

$ git show [SHA]

Synchronize

Fetch down all the branches from that Git remote

$ git fetch [alias]

Merge a remote branch into your current branch to bring it up to date

$ git merge [alias]/[branch]

Transmit local branch commits to the remote repository branch

$ git push [alias] [branch]

Fetch and merge any commits from the tracking remote branch

$ git pull

Merge just one specific commit from another branch to your current branch

$ git cherry-pick [commit_id]

Remote

Add a git URL as an alias

$ git remote add [alias] [url]

Show the names of the remote repositories you’ve set up

$ git remote

Show the names and URLs of the remote repositories

$ git remote -v

Remove a remote repository

$ git remote rm [remote repo name]

Change the URL of the git repo

$ git remote set-url origin [git_url]

Temporary Commits

Save modified and staged changes

$ git stash

List stack-order of stashed file changes

$ git stash list

Write working from top of stash stack

$ git stash pop

Discard the changes from top of stash stack

$ git stash drop

Tracking path Changes

Delete the file from project and stage the removal for commit

$ git rm [file]

Change an existing file path and stage the move

$ git mv [existing-path] [new-path]

Show all commit logs with indication of any paths that moved

$ git log --stat -M

Ignoring Files

/logs/*

!logs/.gitkeep

# Ignore Mac system files
.DS_store

# Ignore node_modules folder
node_modules

# Ignore SASS config files
.sass-cache

A .gitignore file specifies intentionally untracked files that Git should ignore

Tricks

Rename branch

  • Renamed to new_name
$ git branch -m
  • Push and reset
$ git push origin -u
  • Delete remote branch
$ git push origin --delete

Log

Search change by content

$ git log -S''

Show changes over time for specific file

$ git log -p <file_name>

Print out a cool visualization of your log

$ git log --pretty=oneline --graph --decorate --all

Branch

List all branches and their upstreams

$ git branch -vv

Quickly switch to the previous branch

$ git checkout -

Get only remote branches

$ git branch -r

Checkout a single file from another branch

$ git checkout --

Commit

Rewrite last commit message

$ git commit -v --amend

Git Aliases

git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status

See also: More Aliases

Set up the server

添加 git 用户

sudo adduser git

配置 SSH-Key 登录

scp ~/.ssh/id_rsa.pub [email protected]:~/lsong-key.pub

ssh [email protected]
...
mkdir /home/git/.ssh
cat lsong-key.pub >> .ssh/authorized_keys
sudo chown -R git:git /home/git/.ssh
sudo chmod 700 !$
sudo chmod 600 /home/git/.ssh/*

现在应该可以在本地通过 git 用户登录服务器了

开始一个项目

在服务器上启动一个项目

cd ~git/
mkdir project.git
cd project.git
git --bare init

在本地开始这个项目

cd myproject
git init
git add .
git commit -m 'initial commit'
git remote add origin [email protected]:project.git
git push origin master

你也可以 clone 这个项目

git clone [email protected]:project.git

权限控制

读写权限

让需要 git 服务写权限的用户将 SSH 公钥发给你

cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCB007n/ww+ouN4gSLKssMxXnBOvf9LGt4L
ojG6rs6hPB09j9R/T17/x4lhJA0F3FR1rP6kYBRsWj2aThGw6HXLm9/5zytK6Ztg3RPKK+4k
Yjh6541NYsnEAZuXz0jTTyAUfrtU3Z5E003C4oxOj6H0rfIF1kKI9MAQLMdpGW1GYEIgS9Ez
Sdfd8AcCIicTDWbqLAcU4UpkaX8KyGlLwsNuuGztobF8m72ALC/nLF6JLtPofwFBlgc+myiv
O7TCUSBdLQlgMVOFq1I2uPWQOkOWQAHukEOmfjy2jctxSDBQ220ymjaNsHT4kgtZg2AYYgPq
dAv8JggJICUvax2T9va5 gsg-keypair

然后你需要

cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys

这个用户就可以提交了

只读权限

cd ~git/public_html
ln -s ../project.git project.git

要开启需要

cd project.git
mv hooks/post-update.sample ./hooks/post-update
chmod a+x ./hooks/post-update
./hooks/post-update

任何人都可以通过

git clone https://lsong.org/~git/project.git

clone 项目

安全性

你可以用 Git 自带的 git-shell 工具限制 git 用户的活动范围。只要把它设为 git 用户登入的 shell,那么该用户就无法使用普通的 bash 或者 csh 什么的 shell 程序。编辑 /etc/passwd 文件:

sudo vim /etc/passwd

在文件末尾,你应该能找到类似这样的行:

git:x:1000:1000::/home/git:/bin/sh

把 bin/sh 改为 /usr/bin/git-shell (或者用 which git-shell 查看它的实际安装路径)。该行修改后的样子如下:

git:x:1000:1000::/home/git:/usr/bin/git-shell

现在 git 用户只能用 SSH 连接来推送和获取 Git 仓库,而不能直接使用主机 shell。尝试普通 SSH 登录的话,会看到下面这样的拒绝信息:

$ ssh git@gitserver
fatal: What do you think I am? A shell?
Connection to gitserver closed.

Git Server Alternatives