十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Git版本控制及其原理:从入门到精通

Git版本控制及其原理:从入门到精通 目录Git安装ubuntu环境Git基本操作创建本地仓库配置本地仓库对修改进行版本控制了解工作区、暂存区、版本库版本回退撤销修改删除文件Git分支管理创建切换合并分支删除分支解决分支合并冲突分支合并模式分支不隔离优秀Git管理示范例子Git远程操作创建远程仓库克隆远程仓库到本地理解远程推送和拉取向远程仓库推送拉取远程仓库内容了解一下.gitignore文件标签管理操作标签给远程仓库推送标签附录会看git diff命令的输出会看git reflog日志一、短哈希值abc1234二、括号三、操作序号HEAD{n}四、操作类型commit/reset/checkout五、操作描述会看git log --graph --abbrev-commit 的输出给命令取别名Git有什么用对文件进行本地/云端保存以及本地/云端版本管理将文档保存在云端或者本地备份文件丢失后可以恢复文档被修改多次后Git帮我们保存每个版本的文档并指出其相对于上一个版本的修改之处。用户也可以自己添加对这个版本的相应描述。方便查看恢复。Git安装ubuntu环境终端输入sudo apt-get install git -y查看安装是否成功以及安装版本git --versionGit基本操作创建本地仓库计算机上的文件非常多Git并不知道要对哪些文件进行管理。因此我们需要创建一个Git本地仓库只有在本地仓库下的文件才会被Git管理。新建本地仓库命令git init实操配置本地仓库本地仓库必须要配置的就是name和email这是文件提交者的身份标识符Git会把提交者的身份记录下来追溯历史注意他和Git账号密码没有任何关系配置本地仓库命令//只配置本仓库 git config uer.name 你的名字 //新建配置 git config uer.email 你的邮箱 git config --unset uer.name //删除一个配置 git config --unset uer.email //配置这台机器上的所有仓库 git config --global uer.name 你的名字 //新建配置 git config --global uer.email 你的邮箱 git config --global --unset uer.name //删除一个配置 git config --global --unset uer.email //获取本仓库的配置信息 git config -l实操:对修改进行版本控制这一步是把修改的部分从工作区添加到暂存区接着添加到版本库中进行版本控制相关命令git add 文件名(或者“.”表示添加全部修改) git commit -m 在这儿可以填写你对这个版本的描述 git log //查看提交日志实操了解工作区、暂存区、版本库通过.git目录的内容也可以简单验证一下这一点总结一下实际上仓库中每一个版本的文件集都用tree对象组织起来tree中的每个文件的内容都保存在blob对象中tree存放的就是blob对象对应的哈希标识符。commit代表一个版本每个commit对象都有一个tree对象以及上一个版本commit对象的哈希标识符。blob对象存放了每个文件的每个版本的文件内容维护他们就相当于进行版本控制如果一个文件在一次提交中没有被修改那么stage中缓存的文件名-哈希值映射关系没有被覆盖那么就不用创建新的blob对象而是复用上一版本创建的blob对象commit后暂存区的内容暂时不会清空所以暂存区一般保存的就是最新版本的完整的记录包括所有文件-哈希值的映射以及目录结构关于查看工作区、暂存区、已提交版本之间差异以及objects对象内容的命令git status //查看当前git仓库的状态有被添加但是没提交的有没被添加的修改 git cat-file -p objectds对象哈希值 //这是git提供的用来查看objects对象内容的命令 git diff 文件名 //工作区 vs stage的差异add 之后一定没输出因为add之后两个区的内容同步了 git diff --staged 文件名 //stage vs commit的差异add之后有输出但是commit之后没输出版本回退版本回退可以让我们把仓库中的文件恢复到前某个版本的样子相关命令//不同于git log 命令只显示当前版本及之前的提交记录git reflog命令会显示 //历史所有的操作日志包括历史所有的提交记录以及版本回退记录可以用于回退 //后恢复到回退之前的版本(即撤销回退) //git reflog其实就是用户对仓库改变操作的完整记录而git log只是当前版本之前的所有日志的快照 git reflog //soft表示只回退commit对象也就是转换master指向的commit对象 //mixed表示不仅回退commit对象还回退暂存区 //hard表示除了回退以上两者还回退工作区一旦使用这个我们看到的的文件内容就会改变 git reset [--soft | --mixed | --hard] 要回退的版本commit对象的哈希值实操为什么版本回退这么快因为版本回退其实就是修改master文件里存放的哈希值为上一个版本commit对象的哈希值这种简单的修改是很快的就算是使用--hard也不过就是把修改的部分覆盖到暂存区以及工作区罢了。撤销修改撤销修改其实也就是版本回退但是撤销修改发生在不同情况下对应的撤销操作是不同的上面的版本回退其实是撤销修改的一种情况相关命令//这个命令会使用暂存区的内容来对工作区的内容进行恢复 git checkout -- 文件名 //之前讲过也是恢复命令但这里要介绍一个其他用法 git reset [--soft | --mixed | --hard] HEAD //回退到当前版本不改变master内容 git reset [--soft | --mixed | --hard] HEAD^ //回退到上一版本 git reset [--soft | --mixed | --hard] HEAD^^ //回退到上上版本 以此类推......三种情况其实这个很灵活只要明白三个分区以及checkout命令和reset命令分别对哪些分区进行操作就可以按照自己的思路来恢复实操删除文件删除也是一种修改想要进行版本控制和修改一样这里只是介绍一个命令git rm 文件名//相当于 rm 文件名 git add 文件名而且要注意如果新建一个文件然后使用git chekout -- 文件名进行回退结果文件不会如预料的一样被删除需要我们手动删除。因为新建的文件属于Git未跟踪的文件Git找不到历史记录也就不会擅自去改动它。Git分支管理分支可以让我们可以在不同的分支下开发同时开发不同的功能最后合并多人协作开发而不用担心分支互相影响。创建切换合并分支相关命令git branch 新分支的名称 //创建一个新分支 git checkout 要进入的分支名 //切换到目标分支工作 git checkout -b 新的分支名 //创建分支并在切换到这个分支下 git merge 要合并的分支名 //合并分支 git branch //查看所有分支以及当前工作分支实操图形化模拟一下分支过程总结一下HEAD指向的是当前工作分支控制Git的工作对象masterdev等存放的是当前分支的最新版本的commit对象的哈希值HEAD指向的就是他们两个分支不论各自提交多少次都能沿着commit对象中的parent指针回到开始分支时的commit对象也就是说多个分支相当于树的多个分叉。合并之前各分支不会看到对方的修改分支合并如果一方没有修改那这一方就直接指向修改了的分支的最新commit对象这样合并会很快“git rebase 要合并的分支”是变基分支合并但是它和merge不一样他会把合并双方的分支历史变成线性的假设你有这样的历史A---B---C feature / D---E---F---G main用git merge main会生成一个合并提交历史保留了分叉多了一个合并提交MA---B---C---M feature / / D---E---F---G---/ main而用git rebase main会把A、B、C三个提交提取出来在G后面重新应用D---E---F---G---A---B---C feature历史变成一条直线但注意A、B、C是新的提交哈希值变了。删除分支相关命令git branch -d 要删除的分支名 git branch -D 要删除的分支名 //分支有提交未被合并是不可以直接删除的需要用D选项实操解决分支合并冲突如果两个分支修改了同一行内容那么在合并分支的时候git并不知道要保留谁因此就会产生冲突此时我们需要手动解决冲突然后在进行一次提交实操补充可以查看分支提交与合并状况的图形化界面的命令分支合并模式分支合并模式有两种一种是Fast-Forward模式一种是非Fast-Forward模式。一般来说Fast-Forward用于一个分支修改了另一个分支没有修改的情况那么此时合并就是把没有修改的分支对应的最新commit对象更换为修改了的分支对应的最新commit对象。不会也没必要创建新的commit对象。而一般多个分支都有修改的情况用非Fast-Forward模式会创建一个新的commit对象。在log中看不出来Fast-Forward合并和普通master分支提交的区别这样就会导致分支上的所有提交和主分支提交混在一起难以区分一般来说一个分支就是一个功能混在一起的话要剥离出来就比较麻烦因此无论有没有必要最好都使用非Fast-Forward模式进行合并有利于团队协作强制指定Git进行非Fast-Forward合并命令如下git merge -no-ff -m 提交信息 要合并的分支名分支不隔离分支隔离的原理是进入某分支后把当前分支最新的commit对象的内容覆盖到暂存区工作区因此我们在两个分支看到的内容是不一样的。但假如工作区、暂存区有修改未提交这两个区域是共享的转换分支后就不会触发上述机制因为Git要尽可能保护我们的修改内容不丢失因此两个分支修改的内容就会混在一起失去了隔离性谁提交修改就算在谁头上。解决这个问题的方法就是Git提供的相关命令//将工作区的被git追踪管理了add之后的并且做出了修改的文件的修改保存到git仓库中的某文件中 //然后删除修改的内容,工作区此时是干净的 git stash //查看本分支stash文件的内容有什么 git stash list //切换回本分支后再把内容拷贝到工作区 git stash pop这种情况常见于当开发一个新功能还未提交的时候主分支突然出现了bug修复bug的时候不希望看到新功能的代码。或者说开发者在开发过程中想看一眼修改之前的代码实操优秀Git管理示范例子Git远程操作到目前为止我们都是在自己的电脑上进行版本控制但无法多人协作开发虽然说有分支的机制但是总不可能两个人用一台电脑交换着开发吧。Git提供一个中央服务器充当用户的远程仓库他有如下用处代码云端存储本地丢失后还能恢复同一个仓库可以被多个用户克隆到本地实现多用户协同开发各个用户在本地仓库进行开发每个用户都可以把自己的仓库修改的部分推送到远程仓库其他用户可以把远程仓库的代码拉取到本地仓库这就实现了数据同步。创建远程仓库README 文件选中该选项后Git 会在仓库根目录自动生成一个标准的 README 模板文件。项目维护者可以在文件中详细说明程序的功能、使用方法、运行环境、编译步骤等关键信息其他使用者查看仓库时能通过阅读这份文件快速了解项目并正确使用程序。Issue 模板文件Git 仓库自带一个问题反馈模块使用者可以在这里提交使用疑问、功能建议或发现的 Bug。项目维护者收到反馈后会进行答疑和问题修复。如果勾选 Issue 模板使用者提交问题时会自动套用固定格式让反馈内容更规范、信息更完整方便维护者快速定位和解决问题。Pull Request 模板文件master 是项目的主发布分支必须保持稳定可用不能直接合并代码。若要将新功能或修复内容合并到 master必须先提交合并申请经过管理员审核通过后才能合并避免直接合并引入 Bug 导致项目无法使用。勾选该模板后提交合并申请时会自动生成规范格式让修改内容、目的、测试情况更清晰降低审核成本。创建完成结果如下点开.gitee目录可以发现两个文件点开看看这两个文件的内容克隆远程仓库到本地Https协议克隆实操SSH协议克隆实操理解远程推送和拉取在讲解本地仓库向远程仓库推送修改/拉取修改也就是本地和远程的数据同步之前我想先让读者理解一件事情无论是拉取还是推送都是本地分支对应的commit链-远程分支对应的commit链而不是仓库-仓库即不是说一拉取本地仓库就合远程仓库一模一样了。下面我举几个例子来帮助读者理解这个问题关于拉取我想放到下面再具体解释。向远程仓库推送相关命令://eg. git push origin master:master origin是远程仓库的默认名字 git push [要操作的远程仓库名] [要推送的本质分支名]:[要把分支推送给远程的哪个分支] //如果本地仓库的某分支和远程仓库的某分支已经建立了关联那么我们可以直接进行push操作这次的话会尝试对所有有关联关系的分支进行变动的推送本地和远程的master分支是自动关联的 git push //查看哪些分支之间有关联关系 git branch -vv //让本地某分支和远程仓库某分支建立关联关系 git branch --set-upstream-to origin/分支名什么是关联关系我们已经知道都是本地分支对应的commit链-远程分支对应的commit链之间的操作所以一般我们要推送就要写很长的命令“git push [要操作的远程仓库名] [要推送的本质分支名]:[要把分支推送给远程的哪个分支]”。但如果本地分支和远程仓库建立起一一对应的关系那么只需要使用git pushgit也就知道要把那个分支推送向哪个远程分支了。实操可以再举个例子拉取远程仓库内容要理解拉取首先要明白一件事本地仓库中包含了远程仓库的快照。下面简单说明一下相关命令//把远程的所有分支的变动一次性拉取到本地创建的远程仓库的快照中但是不会对本地仓库做出任何修改 git fetch //这个命令可以让我们看到本地包括远程仓库的快照中的所有分支 git branch -a //把远程某分支的commit链拉取下来并与本地的某分支合并 git pull [要操作的远程仓库名] [要从远程仓库拉取的分支名]:[本地仓库的某分支名] //这个命令只会做一件事把当前所在分支对应的远程仓库中的某分支拉取下来并与当前分支合并。注意git pull针对的是当前分支而不是关联了的所有分支(这个和git push不一样)也就是说假设现在本地仓库的当前分支没有关联任何远程分支git pull就会失败即使其他本地分支与远程分支有关联关系 git pull实操了解一下.gitignore文件没错我们之前遇到过这个就是在创建远程仓库的时候勾选一个选项就可以让远程仓库自动生成与某种语言相匹配的.gitignore文件它的作用就是告诉本地仓库哪些文件你不要去管他比如我刚才选的是C类型的.gitignore文件它的内容如下在克隆远程仓库的时候这个文件也是被克隆下来的当然我们也可以在本地仓库自己编写一个名字是.gitignore的文件同样会生效。实操如果你想给一个文件免死金牌就是强制添加管理它有两种方式git add -f 文件名即加-f选项在.gitignore文件中添加一行![文件名]实操还可以通过命令查看某文件是因为ignore文件中的哪一行而被忽略标签管理标签就是给某一次提交的hash值取一个别名这样一来就可以不用查找或记忆它的hash值就能操作本次提交。操作标签相关命令//给提交取别名如果要为最新提交打标签可以省略最后一个参数 git tag [标签名] [要取别名的版本的hash值] //查看当前的所有标签 git tag //在打标签的同时给这个标签添加一些描述 git tag -a [标签名] -m 对这个标签的描述 [要取别名的版本的hash值] //显示标签以及标签对应的版本的详细信息包括对这个标签的描述等 git show [标签名] //删除一个标签 git tag -d [标签名]实操给远程仓库推送标签相关命令//推送某个标签 git push origin [标签名] //推送所有标签到远程 git push origin --tags //删除远程仓库中的某标签 git push origin :[标签名]实操附录会看git diff命令的输出a/xxx 表示修改之前的文件b/xxx表示修改之后的文件ab符号用来区分旧文件和新文件。445a69c旧文件在 Git 中的哈希值blob 对象 ID。4f8b653新文件的哈希值。100644文件权限100表示普通文件644表示所有者可读可写、其他用户只读这样的权限表示方式Bash中也用到。--- a/dir1/profile2 b/dir1/profile2 说明-代表修改之前的文件代表修改之后的文件-1表示旧文件从第1行开始有1行内容被修改 / 删除。1,4表示新文件从第1行开始有4行内容被修改 / 添加。红色-开头的行表示旧文件中被删除的内容这里是删除了hahaha这一行。绿色开头的行表示新文件中新增 / 替换的内容这里是新增了hah、xixix、kkk、666四行。会看git reflog日志整行输出分为 四大核心字段从左到右依次为短哈希值、括号、操作序号、操作类型、操作描述下面逐一拆解。一、短哈希值abc1234每一次 Git 操作对应的唯一提交标识是版本还原的核心依据。我们恢复丢失代码、回退指定版本时直接复制该哈希值即可。如果需要完整哈希值可执行git reflog --full查看。二、括号括号中一般是指向当前版本的分支或者是当前版本对应的标签三、操作序号HEAD{n}代表本地操作的时间顺序是 reflog 最具辨识度的标识HEAD{0}最近一次的本地操作HEAD{1}上一次操作HEAD{2}上上次操作简单记数字越大操作时间越早。四、操作类型commit/reset/checkout记录当前行对应的 Git 操作命令常见类型如下commit本地新建代码提交reset执行了版本回退操作checkout切换分支或切换代码版本merge执行了分支合并操作rebase执行了变基操作pull拉取远程仓库代码。五、操作描述对当前操作的补充说明提交操作会显示自定义的提交备注重置操作会显示回退目标切换分支操作会显示切换的源分支和目标分支直观还原操作场景。会看git log --graph --abbrev-commit 的输出这个命令就是以图形化方式显示出当前所在分支不是所有分支哦的commit提交链*号代表的是一次提交红绿色的线条代表的是分支。给命令取别名相关命令git config alias.[别名] [被取别名的命令或选项] //在config后面加上--global就是全局配置实操
返回列表