大部分校招新人都有两大天敌:Linux和Git。企业的项目开发和在学校里做课设,有着天壤之别。除了开发流程更规范,对团队协作要求更高。
记得我当年实习的时候,第一次参与真正的企业项目开发。刚开始Mentor给了两个很简单的小需求让我写,写完之后让我把我写的代码push到公司的仓库里。结果尴尬的是,我特么不会啊!最后还是Mentor帮我push上去,着实有亿点点丢人!
因此,我打算写两篇文章详细记录一下Git的原理和用法。这一篇里先记录日常使用频率较高的Git命令,希望对各位新人有所帮助。
读取并配置Git
Git中有全局配置和项目(局部)配置,全局配置保存在系统根目录下的
.gitconfig
文件中,这里的根目录在Windows中是C:\Users\用户名\.gitconfig
;在Mac和Linux中,是~/.gitconfig
和/etc/.gitconfig
。 显而易见,项目中的Git配置只对该项目生效,Git配置的生效顺序是项目配置 > 全局配置,也就是说如果两个配置文件有冲突,会以项目配置为准。
Git提供了一个通用的命令git config
来读取或设置配置信息。具体地查看或修改某一个配置,则需要在git config
命令后面加上相应参数。常用命令如下:
git config --list #查看所有配置信息
git config <configKey> #查看某一项具体配置的值
git config <configKey> <configValue> #设置该项目中某一项git配置的值
git config --global <configKey> <configValue> #在全局配置中设置某一项git配置的值
#例如:
git config user.name "Asherz" #设置本项目中用户名称
git config --global user.email "hellozhugj@gmail.com" #全局设置用户邮箱
git config --global core.editor vim #全局设置文本编辑器为vim
工作中常用命令
如果是一个远程仓库中已有的项目,我们只需要将其clone到本地中即可。clone下来的项目中已经包含有.git文件夹(主要包括git跟踪和管理项目的文件),clone完成后就可以直接上手开发了。
git clone <repositoryUrl> <localPath> #将远程仓库中所有文件拉取到本地指定路径下
#例如:
git clone git@gitee.com:zhuganjun/helloWorld.git #将这个gitee上的仓库拉取到当前路径下
git clone git@gitee.com:zhuganjun/helloWorld.git D:\WorkSpace #将远程仓库拉取到D盘WorkSpace路径下
但是如果是一个远程仓库中没有的项目,那么我们首先需要创建一个新的空的远程仓库(在github、gitee或公司私库上添加一个new repository),然后初始化本地工程为git项目,再将本地的git项目与远程仓库关联,最后将本地项目推送到远程仓库。
git init #将当前路径初始化为git管理的仓库(新建了一个.git文件夹,所有版本管理的文件都保存在这里)
git remote add <alias> <repositoryUrl> #为该项目添加一个远程仓库,并为其设置别名
例如:
git init #将当前路径初始化为git仓库
git remote add origin git@gitee.com:zhuganjun/myserver.git #将当前本地仓库关联到远程仓库中,并为该远程仓库起一个别名为origin
git remote -v #查看当前项目关联了哪些远程仓库及其别名
git remote remove test #删除别名为test的远程仓库的关联
Git将整个本地仓库分为三个区域:工作区、暂存区和版本库。工作区就是我们工作的区域,例如我们在IDEA中修改了某一个文件或者增加了某一个文件,这个文件就处在工作区中,工作区的文件内容是没有被git跟踪的。
此时,我们需要使用status命令来查看当前项目状态。一般会输出三个部分:分支信息、提交(commit)信息、是否有未跟踪的文件。未跟踪意味着在Git之前的快照中没有这些文件,Git不会自动将其纳入跟踪范围(防止一些自动生成的二进制文件被包含进项目里)。
git status #查看当前项目状态,是否有未保存到暂存区或者未提交到版本库的更改
git status -s #简洁紧凑地输出当前项目状态 (??
–新添加的未跟踪文件; A
–新添加到暂存区的文件; M
–修改过的文件:M出现在右边表示该文件被修改了但未放入暂存区,左边表示该文件被修改且已放入暂存区)
在工作完成后,我们需要将我们所做的修改添加进git版本库中,此时要用到的就是
add
命令。这个命令有多种功能: 1. 跟踪文件。参数也可以使用目录的路径,这种情况下,会自动跟踪该目录下的所有文件; 2. 暂存更新。跟踪的文件如果被修改了,需要放入暂存区,然后再提交。add命令可以将跟踪的文件放入暂存区中。 因此,add命令可以理解为“添加内容到下一次的提交中”。
注意:如果使用了add命令添加了file之后,还没提交之前,又修改了file,再提交的时候,最后的修改不会被提交上去。原因是,commit默认提交的是add命令的最新版本,而不是工作目录的最新版本。所以,这种情况下,要重新使用add命令将file添加到暂存区。
git add <filePath> #添加指定目录及其子目录下所有文件到暂存区
git add <file1Name> <file2Name>… #添加file1、file2… 到暂存区中
git add . #添加当前目录下所有文件到暂存区(推荐使用这个,比较方便)
在将修改保存到暂存区后,我们还需要提交暂存区里的所有更新到版本记录中。在此之前,一定要确认所有的更新都已经
add
过,否则提交的时候不会记录这些还没暂存的变化。所以,每次提交前最好都使用git status
查看。
如果没有使用-m
, 裸奔的方式会启动文本编辑器以输入本次提交的说明(一般是 vim 或者 emacs,可以用上述的配置命令配置); 使用git commit -a
后Git会自动把所有已经跟踪的文件暂存起来一并提交,从而跳过git add
步骤(更新文件多的情况下,一条一条add,太过繁琐)
如果提交之后发现有几个文件忘了加上去,或者提交信息写错了,此时可以用git commit --amend
尝试重新提交,最终只会有一个提交,第二次的提交将代替第一次提交的结果。
git commit -m “本次提交的说明” #将暂存区中的修改更新到版本中
#例如:
git commit -m "这是第一次提交"
git add forgotten_file
git commit --amend
上面的所有工作都只是在本地进行,并没有能够与他人合作共享,所以,我们需要把我们本地的工作版本
push
到远程仓库中,这样其他人才能拉取到我们的工作成果。
git push <alias> <localBranchName>:<remoteBranchName> #将本地分支推送到远程仓库的指定分支上
#例如:
git push origin master:hello-2.0 #将本地master分支推送到远程hello-2.0仓库中
git push origin master #如果本地分支与远程仓库分支名称相同,则可以省略远程仓库分支不写
git push origin HEAD:refs/for/hello-2.0 #推送,并等待代码评审
git push --force origin master #本地版本与远程版本有差异时,可以使用force参数强制推送
git push origin --delete master #删除远程仓库master分支
每次开始工作前,我们需要拉取当前项目最新的版本
git pull <alias> <remoteBranchName>:<localBranchName>
#例如:
git pull origin master:branch-test #将远程仓库中的master拉取到本地的branch-test分支合并)
git pull origin master #将远程仓库master分支与当前本地master分支合并
其他常见命令
git diff #显示更新内容
diff命令能够显示两个信息:当前还未暂存的更新;当前还未提交的更新。注意:
git diff
本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。也就是说,如果一次性暂存(git add)了所有更新的文件后,再运行diff命令,会什么也得不到。此时需要使用git diff --cached
查看已经暂存的变化。
git reset HEAD <fileName> #取消暂存的文件
git checkout - - <fileName> # 撤销对文件的修改
git rm <fileName> #移除某个文件
从Git中移除某个文件,需要从以跟踪文件列表中移除(准确的说,是从暂存区移除),然后提交。rm 命令可以完成上诉工作,并从工作目录中删除指定文件。
删除已经修改或并放入暂存区的文件,需要使用git rm -f <fileName>
强制删除。
如果想要把文件从Git仓库中删除,但是保留在工作目录中,可以使用git rm --cached <fileName>
。
rm命令后面也可以跟上目录的路径,或者使用glob模式,比如:git rm log/\*.log
,这里的星号*
之前的\
,因为Git有自己的文本模式匹配方式,不需要shell来帮忙展开,这个命令删除log目录下所有拓展名为.log的文件。
git mv <fileFrom> <fileTo> #该命令可以用来给文件重命名
git log #回顾提交历史
不使用任何参数的话,默认按提交时间列出所有更新。加上参数的常见用法有:
git log -p -2
其中-p
显示每次提交的内容差异,-2
表示仅显示最近两次提交;
git log --stat
列出每次提交所有被修改过的文件、有多少文件被修改了以及被修改过的文件的哪些行被移除或是添加了。 在每次提交的最后还有一个总结;
git log --pretty
这个选项可以指定使用不同于默认格式的方式展示提交历史。 这个选项有一些内建的子选项供你使用。 比如用 oneline 将每个提交放在一行显示,查看的提交数很大时非常有用。 另外还有 short,full 和 fuller 可以用,展示的信息或多或少有些不同
git checkout -b <newBranchName> #本地创建一个新的分支,并切换到该分支
这个命令通常和
git push origin <newBranchName>
一起使用,能将本地新增的分支添加到远程仓库
默认忽略文件
对于那些无需纳入Git管理的,不希望出现在未跟踪文件列表的文件,如:自动生成的日志文件、编译过程中的临时文件、二进制文件等。可以创建一个名为
.gitignore
的文件,列出要忽略的文件模式。
可以输入在终端输入cat .gitignore
查看这个文件的内容,例如:
$ cat.gitignore
*.o
*.a
*~
上面第二第三行表示忽略以.o和.a结尾的文件,第三行则忽略所有以~结尾的文件。.gitignore
文件格式规范如下:
- 以
#
开头的行是注释,不会被Git读取 - 可以使用标准的
glob
模式匹配 - 匹配模式可以以
/
开头,防止递归 - 匹配模式可以以
/
结尾,指定目录 - 要忽略制定模式以外的文件或目录,可以在模式前加上
!
取反
所谓的glob模式是指shell所使用的简化版正则表达式:
*
匹配零个或多个任意字符;
[abc]
匹配任何一个列在方括号里的字符,这个例子里匹配字符a、b、c中的任意一个;
?
只匹配一个任意字符;
方括号中使用短横线分隔两个字符,表示这两个字符之间的所有字符都可以匹配,如[0-9]
表示匹配所有0到9之间的数字;
**
表示匹配任意中间目录,如a/**/z
可以匹配a/z, a/c/z, a/cfv/dgr/z等等。
下面是一个常见的实例:
