Git常用命令总结
想要学会使用Git,首先需要理解什么是分布式版本库,什么是工作区和暂存区,这几个概念是理解很多命令的基础。强烈推荐阅读廖雪峰老师写的Git教程,这是目前为止最好的中文Git教程,没有之一。如果你想要成为Git专家请参考《Pro Git》(Second Edition)。
先简单地解释一下工作区、版本库和暂存区。看不懂没关系,先了解下后面的git add
和git commit
命令后再看就容易理解了。(如果还是没有明白,点这里。)
- 工作区:你的工作目录,你的工程文件夹。
- 版本库:就是你工作区中的
.git
文件夹,这里忠实地记录着你提交过的每一次改动。git commit
命令就是把你的改动从暂存区提交到了版本库的当前分支,比如默认的master
分支。 - 暂存区:需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。也就是使用
git add
后文件修改就保存到了暂存区,以备使用git commit
命令提交到真正的版本库。
这里只对常用命令做一下梳理,这些命令基本可以满足日常使用,注意所有git
命令都要在你项目的根目录下使用。
创建仓库
$ git init
添加到暂存区
创建仓库之后就可以使用git管理当前目录下的代码了。同时该目录下多了一个.git
的子目录,用ls -a
可以查看。
$ git add filename
把修改添加到暂存区,每次修改后都需要运行git add
命令,之前已经add
过得文件也一样,如果不add到暂存区,那就无法commit
。因为git
记录的是修改而不是你文件的拷贝,这也是它可以如高效和节约空间的原因。(使用过git add
命令的文件状态就是Tracked
,新建的文件状态是Untracked
。)
$ git add .
把所有文件添加到暂存区。
忽略某些文件
有些文件我们无需Git
管理,也不希望看到它出现在Untracked
列表里面,比如使用Vim
时产生的.swp
临时文件。我们只要创建一个名为.gitignore
的文件,列出要忽略的文件模式即可,支持简单地正则表达式(其实是glob
模式匹配,shell中使用的简化了的正则表达式)。
看一个《Pro Git》中给的.gitignore
文件的例子就懂了:
# 此为注释,会被 Git 忽略
# 忽略所有 .swp 结尾和 .a 结尾的文件
*.a
# 但 lib.a 除外
!lib.a
# 忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
/TODO
# 忽略 build/ 目录下地所有文件
build/
# 忽略 doc/ 目录下的所有 .txt 文件,但不包括 doc/ 子目录中的 .txt 文件
doc/*.txt
# 忽略 doc/ 目录下的所有 .txt 文件,包括 doc/ 子目录中的 .txt 文件
doc/**/*.txt
那些讨厌的临时文件再也不会在git add
的时候捣乱,也不会出现在Untracked
列表里了。
提交
$ git commit -m "wrote a new file"
把文件提交到版本库,-m
后面输入的是本次提交的说明,方便以后从历史记录里找到改动记录。
如果不想每次都要git add
,git commit
怎么办,有一个简单地办法,使用-a
参数:
$ git commit -a -m "I did some work"
这样即使是上次提交之后修改过的文件(Tracked
)也可以直接提交到版本库中(当前的分支)。
查看状态
$ git status
查看版本库状态,就是告诉你哪个文件修改已经在暂存区了(to be commit
),哪个文件已经add
过但是最后的修改没有add
(Changes not staged for commit
),哪个文件是新建的还没有add
过(Untracked
)。
查看日志
$ git log
git log
命令显示所有提交,从最早的提交到最近一次提交(当前HEAD所指向的提交,请参考版本回退)。
$ git log --pretty=oneline
加上--pretty
参数后可以单行输出。
$ git reflog
用来记录你的每一次命令,包括回退命令。
版本回退
在Git中,用HEAD表示当前版本,也就是最新的提交。
$ git reset --hard HEAD^
这个命令表示回退到当前HEAD的上一个版本,也就是舍弃了最后一次提交。会退后再使用git log
命令将无法查看最后一次提交的记录,只能看到当前HEAD,以及更早的提交。可以使用git reflog
命令查看所有提交记录。
$ git reset fc142e435432984a95b46bb7b757b9bdcee0e8e8
git reset
后的参数是通过git reflog
查看到的你希望回退到的版本,可以是任意提交过的版本。
撤销修改
$ git checkout -- filename
命令git checkout -- filename
意思就是,把filename
文件在工作区的修改全部撤销,这里有两种情况:
-
文件修改后还没有
add
到暂存区,撤销修改就回到最后一次commit
时的状态; -
已经
add
后又作了修改,撤销修改就回到最后一次add
时的状态。
如果你乱改了文件还add
到了暂存区,想要回到上一次commit
时的状态,先使用命令git reset HEAD filename
,使暂存区文件恢复到和commit
时一致,再使用git checkout -- filename
。
注意:git checkout -- file
命令中的--
很重要,没有--
,就变成了“创建一个新分支”的命令。
删除文件
直接删除摸个文件,或者用rm filename
命令删除,然后使用命令:
$ git rm filename
然后commit
就可以了。如果不小心删错了文件并且没有commit
,没关系,冷静一下,使用上面一条命令git checkout -- filename
就可以恢复了。
如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。
查看分支
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。默认分支是master
,也是HEAD指向的分支。
$ git branch
前面有*
的分支是当前分支。
新建分支
$ git branch branchname
比如git branch dev
命令创建了一个叫dev
的分支,现在dev
和master
指向相同的提交。
切换分支
$ git checkout branchname
使用git checkout dev
后,HEAD就指向了dev
,现在提交的修改就会到dev
分支上,而master
分支会停留在当前状态。
创建+切换分支
$ git checkout -b branchname
前面两条命令合并成一条。
合并某分支到当前分支
$ git merge branchname
比如当前分支是master
,使用git merge dev
,会将dev
分支上的提交添加到master
分支上。这种合并方式是快速合并(Fast-forward)当两个分支都做过修改后合并是可能会产生冲突,无法进行快速合并,当Git无法自动合并分支时,就必须首先解决冲突。
删除分支
$ git branch -d branchname
合并完成后,就可以放心地删除dev分支了。合并后再删掉分支,和直接在master分支上工作效果是一样的,但过程更安全。
查看文件差异
$ git diff
比较工作区和暂存区的差异。
$ git diff filename
比较同一个文件在不同分支的差异。
$ git diff branchname
比较当前分支和branchname
分支的差异。
$ git diff --cached
// or git diff --staged
比较暂存区和HEAD的差异。
$ git diff --HEAD
比较工作区和HEAD的差异。
解决冲突
git merge
命令会标记有冲突的文件内容,使用git status
可以查看冲突文件,使用git diff filename
可以查看文件内容,比较不同分支上的差异。
打开有冲突的文件,解决冲突,再提交,合并完成。
用带参数的git log --graph
可以看到分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit
现在,你已经可以使用Git在自己的机器上愉快地玩耍啦^_^。