程序员必备基础:Git 命令全方位学习
那么,集中化的版本控制系统又是什么呢,说白了,就是有一个集中管理的中央服务器,保存着所有文件的修改历史版本,而协同开发者通过客户端连接到这台服务器,从服务器上同步更新或上传自己的修改。
![](https://static001.geekbang.org/infoq/b4/b42fed598911d1981b13f32ae032d9b3.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
什么是分布式版本控制系统?
分布式版本控制系统,就是远程仓库同步所有版本信息到本地的每个用户。嘻嘻,这里分三点阐述吧:
用户在本地就可以查看所有的历史版本信息,但是偶尔要从远程更新一下,因为可能别的用户有文件修改提交到远程哦。
用户即使离线也可以本地提交,push 推送到远程服务器才需要联网。
每个用户都保存了历史版本,所以只要有一个用户设备没问题,就可以恢复数据啦~
![](https://static001.geekbang.org/infoq/71/712c0968b2cf565231795ccd59e2ff9e.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
什么是 Git?
Git 是免费、开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。
![](https://static001.geekbang.org/infoq/91/91eae430dac455ce38e60cea898d16b6.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Git 的相关理论基础
Git 的四大工作区域
Git 的工作流程
Git 文件的四种状态
一张图解释 Git 的工作原理
Git 的四大工作区域
先复习 Git 的几个工作区域哈:
![](https://static001.geekbang.org/infoq/01/010565b9bf8dfb202dd9a906095f07f8.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Workspace:你电脑本地看到的文件和目录,在 Git 的版本控制下,构成了工作区。
Index/Stage:暂存区,一般存放在 .git 目录下,即.git/index,它又叫待提交更新区,用于临时存放你未提交的改动。比如,你执行 git add,这些改动就添加到这个区域啦。
Repository:本地仓库,你执行 git clone 地址,就是把远程仓库克隆到本地仓库。它是一个存放在本地的版本库,其中 HEAD 指向最新放入仓库的版本。当你执行 git commit,文件改动就到本地仓库来了~
Remote:远程仓库,就是类似 github,码云等网站所提供的仓库,可以理解为远程数据交换的仓库~
Git 的工作流程
上一小节介绍完 Git 的四大工作区域,这一小节呢,介绍 Git 的工作流程咯,把 git 的操作命令和几个工作区域结合起来,个人觉得更容易理解一些吧,哈哈,看图:
![](https://static001.geekbang.org/infoq/00/0084ac1e45da9adedef3cac8e05b8066.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git 的正向工作流程一般就这样:
从远程仓库拉取文件代码回来;
在工作目录,增删改查文件;
把改动的文件放入暂存区;
将暂存区的文件提交本地仓库;
将本地仓库的文件推送到远程仓库;
Git 文件的四种状态
根据一个文件是否已加入版本控制,可以把文件状态分为:Tracked(已跟踪)和 Untracked(未跟踪),而 tracked(已跟踪)又包括三种工作状态:Unmodified,Modified,Staged
![](https://static001.geekbang.org/infoq/8f/8fb2140bb47f872794a68e57bdda645b.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Untracked: 文件还没有加入到 git 库,还没参与版本控制,即未跟踪状态。这时候的文件,通过 git add 状态,可以变为 Staged 状态
Unmodified:文件已经加入 git 库, 但是呢,还没修改, 就是说版本库中的文件快照内容与文件夹中还完全一致。Unmodified 的文件如果被修改, 就会变为 Modified. 如果使用 git remove 移出版本库, 则成为 Untracked 文件。
Modified:文件被修改了,就进入 modified 状态啦,文件这个状态通过 stage 命令可以进入 staged 状态
staged:暂存状态. 执行 git commit 则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为 Unmodified 状态.
一张图解释 Git 的工作原理
![](https://static001.geekbang.org/infoq/1c/1c70e474bfbeae29778d50a840ee8371.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
日常开发中,Git 的基本常用命令
git clone
git checkout -b dev
git add
git commit
git log
git diff
git status
git pull/git fetch
git push
这个图只是模拟一下 git 基本命令使用的大概流程哈~
![](https://static001.geekbang.org/infoq/1c/1cd2e73a88474d74c5eff3da5ae0abc2.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git clone
当我们要进行开发,第一步就是克隆远程版本库到本地呢
git clone url 克隆远程版本库
![](https://static001.geekbang.org/infoq/16/167dc558f8a76e34983c2b2b1cfe8638.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git checkout -b dev
克隆完之后呢,开发新需求的话,我们需要新建一个开发分支,比如新建开发分支 dev
创建分支:
git checkout -b dev 创建开发分支 dev,并切换到该分支下
![](https://static001.geekbang.org/infoq/8e/8e4bd128ee1f7df428ae2cc4dadb6719.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git add
git add 的使用格式:
git add Hello.java 把 HelloWorld.java 文件添加到暂存区去
有了开发分支 dev 之后,我们就可以开始开发啦,假设我们开发完 HelloWorld.java,可以把它加到暂存区,命令如下
git add Hello.java 把 HelloWorld.java 文件添加到暂存区去
![](https://static001.geekbang.org/infoq/da/da2f30d1eef0c92783d8cc012d87b35a.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git commit
git commit 的使用格式:
git commit -m 'helloworld 开发'
把 HelloWorld.java 文件加到暂存区后,我们接着可以提交到本地仓库啦~
git commit -m 'helloworld 开发'
![](https://static001.geekbang.org/infoq/b5/b5d4697908924e158da5175aec7ada42.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git status
git status,表示查看工作区状态,使用命令格式:
git status 查看当前工作区暂存区变动 git status -s 查看当前工作区暂存区变动,概要信息 git status --show-stash 查询工作区中是否有 stash(暂存的文件)
当你忘记是否已把代码文件添加到暂存区或者是否提交到本地仓库,都可以用 git status 看看哦~
![](https://static001.geekbang.org/infoq/46/465e7d77f1af01110c10b0cb833bd384.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git log
git log,这个命令用得应该比较多,表示查看提交历史/提交日志~
git log 查看提交历史 git log --oneline 以精简模式显示查看提交历史 git log -p <file> 查看指定文件的提交历史 git blame <file> 一列表方式查看指定文件的提交历史
嘻嘻,看看 dev 分支上的提交历史吧~要回滚代码就经常用它喵喵提交历史~
![](https://static001.geekbang.org/infoq/69/6952dcad8536a55ccecb9d0998a24b61.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git diff
git diff 显示暂存区和工作区的差异 git diff filepath filepath 路径文件中,工作区与暂存区的比较差异 git diff HEAD filepath 工作区与 HEAD ( 当前工作分支)的比较差异 git diff branchName filepath 当前分支的文件与 branchName 分支的文件的比较差异 git diff commitId filepath 与某一次提交的比较差异
如果你想对比一下你改了哪些内容,可以用 git diff 对比一下文件修改差异哦
![](https://static001.geekbang.org/infoq/2d/2d03c7335d172e87c2bbcfa2379389c9.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git pull/git fetch
git pull 拉取远程仓库所有分支更新并合并到本地分支。git?pull?origin?master?将远程 master 分支合并到当前本地分支 git pull origin master:master 将远程 master 分支合并到当前本地 master 分支,冒号后面表示本地分支 git fetch --all 拉取所有远端的最新代码 git fetch origin master 拉取远程最新 master 分支代码
我们一般都会用 git pull 拉取最新代码看看的,解决一下冲突,再推送代码到远程仓库的。
![](https://static001.geekbang.org/infoq/c6/c6117e1fc4aee9533b1057e06499ffe0.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
有些伙伴可能对使用 git pull 还是 git fetch 有点疑惑,其实 git pull = git fetch+ git merge。pull 的话,拉取远程分支并与本地分支合并,fetch 只是拉远程分支,怎么合并,可以自己再做选择。
git push
git push 可以推送本地分支、标签到远程仓库,也可以删除远程分支哦。
git
push origin master 将本地分支的更新全部推送到远程仓库 master 分支。git push origin -d <branchname> 删除远程 branchname 分支 git push --tags 推送所有标签
如果我们在 dev 开发完,或者就想把文件推送到远程仓库,给别的伙伴看看,就可以使用 git push origin dev~
![](https://static001.geekbang.org/infoq/c8/c8af2bc3640885ac7ac3194b42978d76.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Git 进阶之分支处理
Git 一般都是存在多个分支的,开发分支,回归测试分支以及主干分支等,所以 Git 分支处理的命令也需要很熟悉的呀~
git branch
git checkout
git merge
git branch
git branch 用处多多呢,比如新建分支、查看分支、删除分支等等
新建分支:
git checkout -b dev2 新建一个分支,并且切换到新的分支 dev2git branch dev2 新建一个分支,但是仍停留在原来分支
![](https://static001.geekbang.org/infoq/ab/abe5d8fb1b9e57e249d9d797d1d3f03e.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
查看分支:
git branch 查看本地所有的分支 git branch -r 查看所有远程的分支 git branch -a 查看所有远程分支和本地分支
![](https://static001.geekbang.org/infoq/08/0886676f27502130692af00065428ef7.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
删除分支:
git branch -D <branchname> 删除本地 branchname 分支
![](https://static001.geekbang.org/infoq/22/22adcd85970125361ebdfb8d179b6f45.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git checkout
切换分支:
git checkout master 切换到 master 分支
![](https://static001.geekbang.org/infoq/d1/d149b71e0c90d2f2c446ddd572c36ac8.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git merge
我们在开发分支 dev 开发、测试完成在发布之前,我们一般需要把开发分支 dev 代码合并到 master,所以 git merge 也是程序员必备的一个命令。
git merge master 在当前分支上合并 master 分支过来 git merge --no-ff origin/dev 在当前分支上合并远程分支 devgit merge --abort 终止本次 merge,并回到 merge 前的状态
比如,你开发完需求后,发版需要把代码合到主干 master 分支,如下:
![](https://static001.geekbang.org/infoq/3b/3b8348a98da6e413b670deb91c06299c.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Git 进阶之处理冲突
Git 版本控制,是多个人一起搞的,多个分支并存的,这就难免会有冲突出现~
Git 合并分支,冲突出现
同一个文件,在合并分支的时候,如果同一行被多个分支或者不同人都修改了,合并的时候就会出现冲突。
举个粟子吧,我们现在在 dev 分支,修改 HelloWorld.java 文件,假设修改了第三行,并且 commit 提交到本地仓库,修改内容如下:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello,捡田螺的小男孩!"); }}
我们切回到 master 分支,也修改 HelloWorld.java 同一位置内容,如下:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello,jay!!"); }}
再然后呢,我们提交一下 master 分支的这个改动,并把 dev 分支合并过下,就出现冲突啦,如图所示:
![](https://static001.geekbang.org/infoq/4b/4b2af9bd29840b5ff2855184701caf62.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Git 解决冲突
Git 解决冲突步骤如下:
查看冲突文件内容
确定冲突内容保留哪些部分,修改文件
重新提交,done
1.查看冲突文件内容
git merge 提示冲突后,我们切换到对应文件,看看冲突内容哈,,如下:
![](https://static001.geekbang.org/infoq/67/67b03d0636abdc1a8a9c00f58d2fbd9e.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
2.确定冲突内容保留哪些部分,修改文件
Git 用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,
<<<<<<<HEAD 是指主分支修改的内容,>>>>>>> dev 是指 dev 分支上修改的内容
所以呢,我们确定到底保留哪个分支内容,还是两个分支内容都保留呢,然后再去修改文件冲突内容~
3.修改完冲突文件内容,我们重新提交,冲突 done
![](https://static001.geekbang.org/infoq/d1/d11f323792a12bf43a1855f342d6d4d9.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Git 进阶之撤销与回退
Git 的撤销与回退,在日常工作中使用的比较频繁。比如我们想将某个修改后的文件撤销到上一个版本,或者想撤销某次多余的提交,都要用到 git 的撤销和回退操作。
代码在 Git 的每个工作区域都是用哪些命令撤销或者回退的呢,如下图所示:
![](https://static001.geekbang.org/infoq/5b/5b07cedbfedf960ab65ef5ec78eaa37a.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
有关于 Git 的撤销与回退,一般就以下几个核心命令
git checkout
git reset
git revert
git checkout
如果文件还在工作区,还没添加到暂存区,可以使用 git checkout 撤销
git checkout [file] 丢弃某个文件 filegit checkout . 丢弃所有文件
以下 demo,使用 git checkout -- test.txt 撤销了 test.txt 的修改
![](https://static001.geekbang.org/infoq/c1/c12a723cf0a940f6087ec23ef0c81b72.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
git reset
git reset 的理解
git reset 的作用是修改 HEAD 的位置,即将 HEAD 指向的位置改变为之前存在的某个版本.
为了更好地理解 git reset,我们来回顾一下,Git 的版本管理及 HEAD 的理解
评论