对于开发人员来说,git 算是最常用的工具之一了。今天用了一天的时间学习了 git 的概念和使用流程,在这里整理一些常用命令以备不时之需。

基础

git init 新建仓库
git add <file> 添加到 stage(暂存区)
git commit -m '<备注>' 提交到 HEAD
git status 查看状态
git diff <file> 对比文件
git reset HEAD <file> unstage


回退

git reset --hard <commit_id> 回到原来的版本
git log 可以查看提交历史,以便确定要回退到哪个版本。
git reflog 查看命令历史,以便确定要回到未来的哪个版本。
git checkout -- <file> 直接丢弃工作区的修改,用 HEAD 中的文件替代
改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,第一步用命令 git reset HEAD <file>,第二步参见上一条
git rm <file> 同时在工作区和版本库删除文件,与 add 对应,需commit


远程仓库

git remote add origin git@github.com:ifrederic/learngit.git  关联远程仓库
git push -u origin master  初次 push
git push origin <branch_name>  以后的提交
git clone git@github.com:michaelliao/gitskills.git 克隆远程仓库,默认只有 master 分支,如果要其他分支,需要:
git checkout -b <branch_name> origin/<branch_name>
git remote -v 查看远程库信息


分支

查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
创建+切换分支:git checkout -b <name>
合并分支到当前分支:git merge <name>
删除分支:git branch -d <name>
查看分支合并图:git log --graph --pretty=oneline --abbrev-commit, 其中 --pretty=oneline 表示单行,--abbrev-commit 表示缩写 hash
不使用Fast Forward模式的合并(好处:从分支历史上就可以看出分支信息,便于恢复到合并之前的版本)git merge --no-ff -m "merge with no-ff" dev


Stash(相当于临时“快照”,可以日后恢复)

git stash 储藏工作现场
git stash list 查看“快照”列表
git stash pop 恢复并删除“快照”
git stash apply stash@{0}  恢复但不删除“快照”
git stash drop 删除快照


多人协作

多人协作的工作模式通常是这样:

  • 首先,可以试图用 git push origin <branch-name> 推送自己的修改;
  • 如果推送失败,则因为远程分支比你的本地更新,需要先用 git pull 试图合并;
  • 如果合并有冲突,则解决冲突,并在本地提交;没有冲突或者解决掉冲突后,再用 git push origin <branch-name> 推送就能成功!
  • 如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令 git branch --set-upstream branch-name origin/branch-name

这就是多人协作的工作模式,一旦熟悉了,就非常简单。


标签

git tag 查看所有标签
git tag <name> 用于新建一个标签,默认为HEAD,也可以指定一个commit id:git tag <name> <commit id>
git tag -a <tagname> -m "blablabla..." 可以指定标签信息;
git tag -s <tagname> -m "blablabla..." 可以用PGP签名标签;

标签只存储在本地,不会自动推送到远程,以下是远程标签的操作:
git push origin <tagname> 可以推送一个本地标签;
git push origin --tags 可以推送全部未推送过的本地标签;
git tag -d <tagname> 可以删除一个本地标签;
git push origin :refs/tags/<tagname> 可以删除一个远程标签。


GitHub

在GitHub上,可以任意Fork开源仓库;

自己拥有Fork后的仓库的读写权限;

可以推送pull request给官方仓库来贡献代码。


自定义 Git

忽略特殊文件如.DS_Store.

忽略某些文件时,需要编写.gitignore;.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理。

不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore。例如这是 macOS 系统所需的.gitignore文件:

*.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

设置别名(Alias)

在这个设置中,我们将 unstage 的操作 reset HEAD,设置了别名 unstage

git config --global alias.unstage 'reset HEAD'

以后输入 git unstage test.py 就相当于执行 git reset HEAD test.py 了。另外:

git config --global alias.last 'log -1'

这样,用 git last 就能显示最近一次的提交。甚至,还可以这样:

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

至于有什么效果,就自己尝试吧:)

最后的话

其实一般情况下我们并不需要死记硬背这些命令,使用图形化界面操作 git 是比较方便的。我个人比较推荐的是 JetBrains 家的 IDE 自带的 Version Control 以及单独的 git 图形界面 Tower。不过,Tower 从 2019 年起开始采用订阅制了,并且价格也不便宜。是选用其他工具代替还是 XX,需要自己衡量。