Git入门指南
一、安装Git
要使用Git首先需要进行环境的配置与安装。可以从Git官网直接下载安装程序,地址:https://git-scm.com/downloads,然后按默认选项安装即可。
注意:安装过程中有一步是选择默认主分支,此时有选项让选择master还是main作为默认分支,建议选择main,不再选择默认的master。
安装完成后,进行全局设置:
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
二、添加远程库
可以选择两种方案:
- 本地已存在git项目(即已在本地执行过
git init
命令的),需要同步至远程服务器(如github)的空白仓库。 - 从远程库克隆,选择本地要存放仓库的文件夹的母目录,Git Bash执行命令
git clone
克隆至本地。Git支持多种协议,包括https
,但ssh
协议速度最快。
下面介绍下方案一。
要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git
,通常在远程仓库页面可以直接复制仓库地址。
关联一个远程库时必须给远程库指定一个名字,origin
是默认习惯命名,不建议修改。
关联后,使用命令git push -u origin main
第一次推送main分支的所有内容,后续的push就不需要-u
了。
此后每次在进行N次的本地commit后,可根据频率需要使用命令git push origin main
推送最新修改至远程库。
在被git管理的文件夹下使用git remote -v
可以查看远程库信息,用git remote rm origin
可以删除关联的远程库。
注意:
当你第一次使用Git的clone
或者push
命令连接GitHub时,会得到一个警告:
The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?
这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes
回车即可。
Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.
这个警告只会出现一次,后面的操作就不会有任何警告了。
三、创建版本库
版本库又名仓库 (repository),可以简单理解为一个目录,这个目录里面的所有文件的变化都可以被Git跟踪管理。注意,如果使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文字符。
进入要进行版本控制的项目文件夹下,Git Bash命令行下输入git init
命令,即可把这个目录变成Git可以进行版本控制的仓库。该文件夹下会出现一个隐藏文件夹.git
,里面就是该项目文件夹要进行版本控制的一些系统配置文件的存储地。
添加文件到Git仓库,分两步:
- 使用命令
git add filename
,注意,可反复多次add从而添加多个文件; - 使用命令
git commit -m 'message'
,提交版本。每次提交的版本都可被追溯、回退及版本管理。message建议填写当次commit的简要介绍。
四、版本控制
4.1 工作区和暂存区
工作区(Working Directory)就是你在电脑里能看到的文件夹目录。
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支main
,以及指向main
的一个指针叫HEAD
。
上一步所讲:在把文件添加到Git版本库时是分两步执行的:第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
可以简单理解为:需要提交的文件修改通通放到暂存区,然后一次性提交暂存区的所有修改形成分支的一个节点。
分支可以视需求push到远程仓库。
4.2 版本回退
git log
命令显示从最近到最远的提交日志,如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数,即git log --pretty=oneline
。
看到的一大串类似1094adb...
的就是commit id
(版本号)。
Git允许我们在不同版本历史之间进行切换,使用命令git reset --hard commit_id
即可切换至相应的版本。
HEAD
指向的版本就是当前版本。以当前版本为时间原点,用git log
可以查看提交历史,以便确定要回退到过去的哪个版本的版本号;用git reflog
可查看命令的历史,从而可以找到要前往未来的哪个版本的版本号。
4.3 撤销修改
主要有以下三种情况:
情况A. 如果改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- filename
,既可让这个文件回到最近一次git commit
或git add
时的状态。
情况B. 如果不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改(unstage),分两步:第一步用命令git reset HEAD filename
,就回到了情况A,第二步按情况A的命令进行操作。
情况C:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节进行版本回退,不过前提是没有推送到远程库。
4.4 删除文件
使用命令git rm filename
用于删除一个文件。
在Git中,删除也是一个修改操作,上文的git checkout
本质上就是用版本库里的文件版本替换掉了工作区的文件版本。如果一个文件已经被提交到版本库,那么你永远不用担心误删,随时可以恢复。但是要注意,git只能实现恢复文件到最新版本,最近一次提交之后新修改的内容会永远丢失。
五、分支控制
5.1 创建分支
分支可以理解为由N个commit组成的版本串在一起形成的时间线。
默认分支为main分支,即主分支,可以把main
视为一个指针。每次commit,main
指针都会在分支都向前移动一步。随着不断提交,master
分支的线也越来越长。
Git鼓励大量使用分支,以下是常用命令:
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
创建+切换分支:git checkout -b <name>
或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
5.2 合并分支
使用git merge <name>
命令可以合并某分支到当前分支。
新创建的分支可以合并至主分支,新创建的分支使用完毕后(即合并后)也可以删除。
在合并分支时,如果可能,Git默认会用Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward
模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再次使用commit
命令进行提交,即可合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,
用git log --graph
命令可以看到分支合并图。
5.3 分支策略
在实际开发中,通常建议按照几个基本原则进行分支管理:
首先,main
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面工作;
那在哪里工作呢?日常工作都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到main
分支上,在main
分支发布1.0版本;
团队里的每个人都在dev
分支上工作,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
开发一个新feature,最好新建一个分支。
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>
强行删除。
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除。
当手头工作没有完成时,先把工作区使用git stash
命令暂存一下,然后去修复bug,修复后,再git stash pop
,回到工作现场;
在main分支上修复的bug,想要合并到当前dev分支顺带修补dev分支上的bug,可以用git cherry-pick <commit>
命令,把bug提交的修改“复制”到当前分支(如dev分支),避免重复劳动。
Git分支十分强大,在团队开发中应该充分应用。
5.4 多人合作
多人协作的工作模式通常如下:
- 首先,可以试图用
git push origin <branch-name>
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功!
如果git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。
常用命令:
- 查看远程库信息,使用
git remote -v
; - 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交; - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致; - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
; - 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。
六、特殊配置
6.1 忽略特殊文件
有些时候某些文件必须要存放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件。
这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不需要从头写.gitignore
文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore。
使用git add -f filename
可以忽略.gitignore
文件中定义的规则而强制add某个文件。
忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的
.class
文件; - 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
.gitignore
文件示例:
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class
# 不排除.gitignore和App.class:
!.gitignore
!App.class
把指定文件排除在.gitignore
规则外的写法就是!
+文件名,所以,只需把例外文件添加进去即可。
6.2 配置别名
配置Git的时候,加上--global
是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用,每个仓库的Git配置文件都放在.git/config
文件中。
可以使用git config
命令简写命令,例如用cm
表示checkout
,ci
表示commit
,br
表示branch
。
配置命令示例:
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch
$ git config --global alias.unstage 'reset HEAD'
$ git config --global alias.last 'log -1'
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"