GIT版本控制工具

64 阅读11分钟

什么是git

git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。

git是 Linus Tovalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。

基本配置

用户信息

开发人员的用户信息请使用中文拼音全拼写法,比如“Zhan San”、“Li Si”这样的,注意姓和名首字母大写,中间留一空格,电子邮件地址统一填写公司邮箱,比如“zhangsan@company.cn”。命令行如下

git config --global user.email "邮箱地址"
git config --global user.name "用户名"

环境配置

Windows由于权限系统和macOS有差异,换行也有所不同,所以对于Windows平台使用git需要进行下列配置

git config --global core.filemode false
git config --global core.autocrlf false

如果是macOS系统,则只需要执行

git config --global core.autocrlf false

修改完成后可以通过git config --global -l 查看是否改动成功,请注意一下。

在项目开发中,如果改变了文件或文件夹名称的大小写,默认情况下git是无法检测到的,请执行以下命令关闭大小写忽略。

git config --global core.ignorecase false

查看配置

#列出当前配置
git config --list
#列出Repository配置
git config --local --list
#列出全局配置
git config --global --list
#列出系统配置
git config --system --list

git基本概念

版本库 .git : 当我们使用git管理文件时,比如git init时,这个时候,会多一个.git文件我们吧这个文件称之为版本库。.git文件另外一个作用就是它在创建的时候,会创建master分支,并且将HEAD指针指向master分支。

Workspace:工作区,就是平时进行开发改动的地方,是当前看到最新的内容,在开发过程也就是对工作区的操作(vscode直接编辑的位置)。

Index:暂存区,当执行git add 的命令后,工作区的文件就会被移入暂存区,暂存区标记了当前工作区中哪些内容是被 git 管理的,当完成某个需求或者功能后需要提交代码,第一步就是通过 git add 先提交到暂存区。

Repository:本地仓库,位于自己的电脑上,通过git commit 提交暂存区的内容,会进入本地仓库。

Remote:远程仓库,用来托管代码的服务器,远程仓库的内容能够被分布在多个地点的处于协作关系的本地仓库修改,本地仓库修改完代码后通过 git push命令同步代码到远程仓库。

一般来说,git 的工作流程分为以下几步:

1. 在工作区开发,添加,修改文件。

2. 将修改后的文件放入暂存区。

3. 将暂存区域的文件提交到本地仓库。

4. 将本地仓库的修改推送到远程仓库。

git基本操作

初始化项目

  • git init在项目中初始化Git,让Git管理当前项目

查看状态

  • git status检查当前文件状态

    工作区新建的文件,还没有被git管理(需要add到暂存区后才被git管理)

    Untracked files

    文件位于工作区

    Changes not staged for commit

    文件位于暂存区

    Changes to be committed

    工作区及暂存区都没有修改后未提交的文件

    nothing to commit, working tree clean

git add

  • git add ...将工作区的指定文件添加到暂存区
  • git add .将工作区更改的所有文件都添加到暂存区

git commit

  • git commit提交暂存区的改动到本地仓库,生成版本(会新开编辑器来输入描述信息)
  • git commit -m '描述信息'提交暂存区的改动到本地仓库,生成版本
  • git commit ... -m '描述信息'提交暂存区的指定文件到本地仓库,生成版本
  • git commit -am '描述信息'等同于 git add . && git commit -m '描述信息'
  • git commit --amend -m <描述信息>使用一次新的commit,替代上一次提交(如果代码没有任何新变化,则用来改写上一次commit的提交信息)
  • git show <版本号>显示某次提交的内容变化

**注:**git commit后,暂存区和本地版本库的内容是一致的

git的版本管理,及HEAD的理解
使用git的每次提交,Git都会自动把它们串成一条时间线,这条时间线就是一个分支。如果没有新建分支,那么只有一条时间线,即只有一个分支,在Git里,这个分支叫主分支,即master分支。有一个HEAD指针指向当前分支(只有一个分支的情况下会指向master,而master是指向最新提交)。每个版本都会有自己的版本信息,如特有的版本号、版本名等。如下图,假设只有一个分支:

查看记录

  • git log查看提交记录

  • git log --oneline以一行的方式查看提交记录

  • git log --oneline --graph以一行、图形化的方式查看提交记录

  • git reflog查看全部历史操作记录(包括被git reset“丢弃”的版本)

git reset

git reset --soft HEAD^//常用的一条指令
  • git reset撤回所有暂存区的文件到工作区
  • git reset 撤回指定的暂存区的文件到工作区
  • git reset --soft <版本号>重置本地仓库中的代码到指定版本
  • git reset --mixed <版本号>重置本地仓库和暂存区的代码到指定版本。为默认行为,等价于git reset <版本号>
  • git reset --hard <版本号>重置本地仓库、暂存区和工作目录的代码到指定版本。注意:会覆盖正在开发的代码

gitignore文件

.gitignore文件是一个用于指定哪些文件不需要Git管理(即Git要忽略哪些文件)的文件。示例如下。

# 此为注释

# 忽略指定文件,不让Git管理
test.html

# 忽略所有文件名是test的文件,不管后缀是什么
test.*

# 忽略所有后缀名为.a的文件
*.a

# 但lib.a除外
!lib.a

# 忽略node_modules目录下的所有文件
node_modules/

# 忽略doc/目录下的所有后缀名为.a的文件(会忽略doc/abc.txt但不忽略doc/server/abc.txt)
doc/*.txt

# 仅仅忽略项目根目录下的abc.def文件,不包括subdir/abc.def
/abc.def

# 注:Git管理的是文件,空目录会自动被Git忽略掉

分支管理

查看分支

  • git branch查看本地分支

  • git branch -r查看远程分支

  • git branch -a查看本地和远程分支

  • git branch -v查看分支及各个分支最后一个提交对象的信息(同样可以-va、-vr等命令连用)

创建&切换&删除分支

  • git branch <分支名>在当前分支的节点上创建新的分支
  • git checkout <分支名>切换到指定分支
  • git switch <分支名>切换到指定分支,v2.23.0版及以后可用
  • git checkout -b <分支名>创建并切换到新建分支
  • git branch -d <分支名>删除指定分支
  • 合并分支

git merge <分支名>将指定分支合并到当前分支

注: 合并分支时,要先切换到最终要合并到的分支,再合并。
注: 在两个不同的分支中,如果对同一个文件的同一个部分进行了不同的修改,则合并分支时会产生冲突。此时需要人为解决冲突后再重新提交一次。

git clone
远程操作的第一步,通常是从远程主机克隆一个版本库,这时就要用到git clone命令。

  • git clone <版本库URL>在本地主机生成一个目录,与远程主机的版本库同名
  • git clone <版本库URL> <本地目录名>在本地主机生成一个目录,指定与远程主机的版本库不同的目录名

git remote
为了便于管理,Git可以为远程主机指定主机名。git remote命令就用于管理主机名。
使用git clone命令克隆版本库时的远程主机会默认被Git命名为origin。
主机名与URL的对应关系存储在当前项目的.git/config文件中。

  • git remote列出所有远程主机
  • git remote -v查看远程主机的网址
  • git remote show <主机名>查看指定主机的详细信息
  • git remote add <主机名> <网址>添加远程主机
  • git remote rm <主机名>移除远程主机
  • git remote rename <原主机名> <新主机名>对远程主机进行重命名

stash临时存储
如果当前工作区或暂存区存在未提交的修改,则无法切换分支。所以当我们想把当前修改应用到其他分支时或当我们需要切换到其他分支完成某些任务但又不想立即提交眼前已经修改的代码时,可以先用git stash命令先把工作区及暂存区已经修改的文件临时保存起来,然后再进行分支切换。之后再根据具体情况,在合适的时机从stash中恢复刚刚保存的内容。

  • git stash把本地的改动(工作区或暂存区的改动)临时存储起来

  • git stash pop应用最近一次临时存储的修改,并删除存储记录

  • git stash save "message"执行存储时添加备注

  • git stash list查看stash的存储列表

  • git stash apply应用最近一次存储的修改,但不会把存储从存储列表中删除

  • git stash apply stash@{index}应用stash中标号为index的修改,不会把存储从存储列表中删除

  • git stash clear清空stash缓存

git fetch
一旦远程主机的版本库有了更新,需要将这些更新取回本地,这时就要用到git fetch命令。git fetch命令通常用来查看其他人的进度,因为它取回的代码对你本地的开发代码没有影响。

  • git fetch <远程主机名>将某个远程主机的所有更新,全部取回本地。
  • git fetch <远程主机名> <分支名>取回某个远程主机的指定分支的更新

git fetch取回的更新,在本地主机上要用远程主机名/分支名的形式读取。比如origin主机的master分支,就要用origin/master读取。

// 使用fetch拉取代码后需要使用
//git checkout FETCH_HEAD 切换到一个隐藏分支
//查看别人的代码后在确认是否合并代码
//然后git checkout 自己的分支
//使用 git rebase FETCH_HEAD合并到自己的分支

git pull
git pull命令的作用是,取回远程主机某个分支的更新,再与本地的指定分支合并。

  • git pull <远程主机名> <远程分支名>:<本地分支名>取回远程主机某个分支的更新,再与本地的指定分支合并。比如git pull origin next:master表示 取回origin主机的next分支,与本地的master分支合并。如果远程分支是与当前分支合并,则冒号后面的部分可以省略,写成git pull origin next

实质上,git pull等同于先做git fetch,再做git merge。比如git pull origin next相当于git fetch origin next && git merge origin/next
注:没有本地仓库的时候,用git clone;已经有本地仓库,更新的时候用git pull

git push
git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。

  • git push <远程主机名> <本地分支名>:<远程分支名>将本地指定分支的更新,推送到远程主机指定分支
  • git push <主机名> --delete <远程分支名>删除指定主机的指定分支

注:将本地仓库推送到远程仓库需要权限。仓库创始人默认有权限,其他人需要先加入团队,才能推送。

  • 注意:如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,

  • 注意:分支推送顺序的写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>。

追踪关系
在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在git clone的时候,所有本地分支默认与远程主机的同名分支建立追踪关系,比如本地的master分支自动追踪origin/master分支。

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。
比如git pull origin 表示本地的当前分支与origin主机上相对应的"追踪分支"(remote-tracking branch)进行合并。

git push如果省略远程分支名,则表示将本地分支推送至与之存在追踪关系的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
比如git push origin master 表示将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。
还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用--all选项。
比如git push --all origin表示,将所有本地分支都推送到origin主机。

推荐做法

  • 每天开始工作时,都应该从远程仓库拉取最新的代码

  • 每天工作完,都应该把代码推送到远程仓库

  • 如果使多人协作开发,则每次推送前需要先拉取

为他人的项目贡献代码

  • 把想贡献代码的仓库fork到自己的远程仓库;
  • 在自己的远程仓库做提交;
  • 完成后通过Pull Request向对方贡献代码(需对方审核)