Git 配置与使用详解
1. Git 是什么
Git 是一个版本控制工具,用来记录代码的修改历史。它可以保存每次更改的内容,让开发者能随时回退到之前的版本,也方便多人协作开发代码。
Git 版本控制工具的基础概念、安装配置及常用命令。内容包括仓库管理、分支操作、冲突解决以及远程仓库协作流程。通过 vi 编辑器示例和实际命令行演示,帮助开发者掌握 Git 的核心工作流,实现代码的版本管理与团队协作。

Git 是一个版本控制工具,用来记录代码的修改历史。它可以保存每次更改的内容,让开发者能随时回退到之前的版本,也方便多人协作开发代码。
仓库 (Repository):包含项目所有文件和版本历史的目录
工作目录 (Working Directory):本地文件系统中的项目文件
暂存区 (Staging Area/Index):准备下一次提交的文件集合
提交 (Commit):保存到仓库中的项目快照
分支 (Branch):指向特定提交的轻量级可移动指针
HEAD:指向当前所在分支或提交的指针
远程 (Remote):托管在服务器上的仓库副本
由于本篇文章基本都是在 Git Bash 中示例,会用到一些基本的 linux 命令,列举一些常用命令:
ls / ll:查看当前目录 cat:查看文件内容 touch:创建文件 cd:切换目录 pwd:显示当前路径 cp:复制文件 mv:移动/重命名 rm:删除文件 mkdir:创建目录
同时也会直接在命令行中编辑文件,需要用到 vi 编辑器,所以看看 vi 编辑器的用法:
vi 是一个命令,也是一个命令行下的编辑器,它有如下功能:
很多人不习惯在命令行下编辑文件,在实际开发中也不会经常在命令行下编辑文件,但是在 Linux 系统中对文件做些简单修改时,使用 vi 命令的效率非常高,并且在很多时候,比如现场调试,并没有 GUI 形式的编辑工具,vi 是唯一选择。
常用命令:
vi 编辑器由三种模式,各个模式的侧重点不一样:
以下图示可表示 vi 编辑器三种模式下的切换:
说明:在终端输入 vi 文件名打开文件,这时进入'一般模式'。在一般模式下,按 i或 a键进入'编辑模式',就可以打字修改内容了。在一般模式下,按 :键进入'命令行模式',可以执行保存、退出等命令。
注:不论在哪个模式下,按 Esc 都能退回一般模式。
文件操作 vi 文件名 启动 vi,如果文件存则打开文件,否则新建文件并打开 :q! 强制退出,不保存 :wq / :x 保存并退出 :q 退出 一般模式(光标移动) h/j/k/l 左/上/右/下 0 行首 $ 行尾 gg 文件开头 G 文件末尾 文本编辑 x 删除当前字符 dd 删除当前行 u 撤销 yy 复制当前行 p 粘贴
下载完成后定义好安装目录后无脑点击下一步安装即可。
随后在桌面右键,显示更多选项,如果看到下面两个选项说明安装成功:
其中 Git GUI 是 Git 提供的图形界面工具,Git Bash 是 Git 提供的命令行工具
接下来就是环境变量的配置,找到 Git 安装的目录,复制 bin 和 cmd 文件夹的目录。
如图所示步骤:
打开的界面选择新建,把刚才复制的两个目录粘贴过来,点击确定:
随后,桌面按下 win+R,输入 cmd 回车,打开 cmd 终端,输入 git --version,若出现版本号,则说明 Git 配置成功:
桌面右键选择 Git Bash,输入以下内容,设置用户信息,包括用户名和邮箱,这里推荐使用 Github 的用户名和注册 Github 时的邮箱,方便后续多人协作开发。
git config --global user.name "你的用户名(注意不能出现中文)" git config --global user.email "你自己的邮箱@example.com"
设置好后可以用以下指令查看配置信息:
git config --global user.name // 查看用户名 git config --global user.email // 查看邮箱
另外,有些常用指令参数非常多,每次都要输好多参数,我们可以使用别名,下面为常用的 log 指令配置别名,这样我们后面如果想要查看日志信息就不用每次输一大堆指令。
在 Git Bash 中分别输入以下指令:
echo 'alias git-log="git log --pretty=oneline --all --graph --abbrev-commit"' >> ~/.bashrc source ~/.bashrc git config --global alias.ll "ls -al"
这样后面要想查看提交日志,只用输入 git-log 指令。另外,若想查看当前目录只需输入 ll 指令
在电脑中任意一个位置(推荐 D 盘)创建一个空文件夹作为本地仓库(存储所有 Git 提交记录和文件),随后进入该文件夹,右键打开 Git Bash,输入 git init 初始化本地库:
git init
如果该文件夹中出现一个隐藏的.git 文件,则说明本地库创建成功:
如果没有看到任何文件,看看是不是没有打开查看隐藏的项目:
Git 工作目录下对于文件的修改(包括新建、删除、更新)会存在几个状态,这些修改的状态会随着我们执行 Git 的命令发生变化。
如果新建一个文件那么这个文件就处于未跟踪状态(untracked),修改现有文件就是处于未暂存(unstaged)状态,这时文件都处于工作区,如果执行指令git add,那么文件就会提交到暂存区,处于已暂存状态(staged),这个暂存区可以理解为提交到本地库之前的一个缓存区。如果我们真的要把暂存区的文件提交到本地库作为一个随时可以查看的版本,只需执行git commit指令。提交成功后就形成一次提交记录,并作为一个版本,每次提交都会形成一个版本。
状态之间的转换:
git add:工作区 --> 暂存区git commit:暂存区 --> 本地仓库git status 查看修改的状态(暂存区、工作区) git add 单个文件名 | 通配符 将工作区一个或多个文件添加到暂存区 git add . 将所有修改加入暂存区 git commit -m "提交说明" 提交暂存区内容到本地仓库的当前分支 git log 查看提交日志 git reset --hard commitID 版本切换,其中 commitId 可以使用 git -log 或 git log 指令查看
注:git log 指令的一般形式是:
git log[option]
其中 options:–all 显示所有分支–pretty=oneline 将提交信息显示为一行–abbrev-commit 使得输出的 commitId 更简短–graph 以图的形式显示
如何查看已经删除的记录?
使用 git reflog 指令可以看到已经删除的提交记录
一般总有一些文件无需纳入 Git 管理,也不希望它们出现在未跟踪的文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。在这种情况下,可以在工作目录中创建一个名为.gitignore的文件(文件名固定),列出要忽略的文件模式,比如:
# 忽略 .a 文件 *.a # 不忽略 lib.a 文件,即使上面忽略了所有 .a 文件 !lib.a # 只忽略当前目录下的 TODO 文件,不忽略子目录中的 TODO(只忽略根目录下的 TODO 文件) /TODO # 忽略整个 build 目录 build/ # 忽略 doc 目录下的 .txt 文件,但不包括子目录 doc/*.txt # 忽略 doc 目录及其所有子目录中的 .pdf 文件 doc/**/*.pdf
接下来举一个例子帮助大家更好地理解整个过程:
在自己本地仓库中右键打开 Git Bash,输入 vi file01.txt 创建一个新的文本文件:
这就进入到 vi 编辑器中,注意这一步先不要编辑这个文件,按 Esc 输入:wq 退出 vi 编辑器,随后输入 git status 查看修改状态:
在 git 中,红色代表已做修改(新建,更新)但还没有添加到暂存区的文件,绿色表示已添加到暂存区的变更,准备提交到本地库。所以这里就是表示 file01 文件未跟踪。输入 git add . 将工作区所有修改添加到暂存区,再次输入 git status 查看状态:
可以看到,文件变成绿色,说明已将修改添加到暂存区,这时输入 git commit -m "add file01" 将修改提交到本地库作为一个版本,并输入 git status 再次查看状态:
这时 git 提示了 "nothing to commit,working tree clean" 表明当前暂存区没有任何修改,暂存区是'干净的'。我们可以使用 git log 指令查看提交记录:
红框中就是我们提交时所备注的提交说明,当前只有一个提交,就是创建 file01 文件。再次输入 vi file01.txt,编辑文件内容为 update count = 1,保存并退出 vi 编辑器:
在以上操作中,更新完 file01 文件后进行了保存和提交操作,提交说明为 update file01 表示这次提交是修改了 file01 文件,最后输入 git log 查看提交记录,提交记录显示当前有两次提交,一次是刚才我们创建文件的提交,另一次就是更新文件的提交。
接下来重点说说 reset 版本回退的用法。一般命令形式是 git reset --hard commitID,这里这个 commitID 就是在提交记录中黄色部分:
特别长对吧,这时前面我们配置的 log 别名就可以解决这个问题,输入 git-log 指令:
这样 commitID 就变得非常简单了,取原 ID 的前七位,这样我们就能很方便地跳转到任意一个版本。输入 git reset --hard 74c07c3(你自己的 commitId)回退到新建文件的版本,这时打开文件看看,应该什么都没有:
要注意的是,在 Git Bash 中,Ctrl+C 和 Ctrl+V 是不管用的,要是想要复制 commitID 可以双击它,如果选中就已经复制成功,粘贴只需按一下鼠标滚轮即可。
如果这时我们想要回到刚才那个版本呢?还是一样的操作:
这样就能在已经提交的各个版本之间跳转,非常方便。不过这里还有一个问题,刚刚我们是处于 add 版本,这时使用 git-log 指令是看不到 update 版本的记录的:
当然你可能觉得不能理解,上面的记录不是还有 update 版本的 id 吗?有是没错,但是在实际使用中不一定会一直开着这个界面,有可能是关闭之后第二次打开,这时就不会有任何记录。那我们如何跳转到已经'消失'的那个版本呢?还记得上面介绍的 git reflog 指令吗?这个指令可以看到所有的 git 操作记录,分析操作记录就可以跳转到所谓'消失'的版本:
几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上分离开来进行重大的 Bug 修改、开发新的功能,以免影响开发主线。
就像写文章时的草稿副本:主分支是正式文档功能分支是草稿纸可以在草稿上随意修改,确认无误后再合并到正式文档
常用指令:
git branch 查看本地分支 git branch 分支名 创建本地分支 git checkout 分支名 切换分支 git checkout -b 分支名 创建并切换到分支 git merge 分支名 合并分支到当前分支 git branch -d 分支名 删除分支(需要做各种检查) git branch -D 分支名 删除分支(不做任何检查,强制删除)
看下面合并分支的记录:
注:一个星号就是一个版本 HEAD 指向哪个分支就表示当前处在该分支,HEAD 只是一个标记而已
比如,在上面的例子中:
这里先创建了一个新分支 dev01,随后在 master 分支上新建 .gitignore 文件并提交。使用 git-log 查看提交记录,这里而一看到各个分支的操作记录,当前只是 master 分支上多了一个新建.gitignore 的提交。接着切换到 dev01 分支:
在 dev01 分支上新建 file02 并提交,提交记录显示 dev01 分支上多了一个新建 file02 的记录,两条分支位于两个分叉上。
分别看看不同分支上目录中的文件:
可以看到,master 分支上有.gitignore、file01 文件,dev01 分支上有 file01、file02 文件。也就是说,不同的分支就相当于不同的箱子,装着不同的内容。我们可以在不同的分支上开发不同的功能,各个分支之间是独立的。两个分支上的功能开发完毕,最后要合并到一起,可以使用 git merge 分支名,表示将分支合并到当前分支上,一般是合并到 master 分支上,所以合并之前要确保当前处在 master 分支上:
从合并完成之后的提交记录可以很清楚的看到各个分支之间的关系以及各个分支上的提交记录,展示的是 master 分支上的提交记录,在第三个星号处(从下往上数)master 分支新建.gitignore,然后在分出去的分支上,第四个星号处,新建 file02,接着合并到 master 上,形成最终版本。这时看看 master 分支中的文件:
既有.gitignore,也有 file02,说明合并成功。
当两个开发者开发同一个项目,并且处于两个不同的分支上时,这时若两个人同时修改了同一个文件的同一行,那么在合并的时候就会产生冲突,Git 也不知道采用哪个人的修改,Git 就会把这个问题抛给我们,让我们来决定采用哪个版本的修改。我们解决这个问题的过程就叫做解决冲突。解决冲突的过程如下:
现在,在上面的例子中来制造一些冲突来帮助我们更好地理解解决冲突的流程:
首先输入 git-log 查看当前分支,日志显示当前存在 master 分支和 dev01 分支,由于 dev01 分支和 master 分支不是完全相同的,这时我们先删掉 dev01 分支,随后创建并切换到 dev 分支上:
然后分别在 dev、master 分支上修改 feile01 文件的 count 为不同的值,这时就产生了冲突,如果这时我们想要把 dev 分支合并到 master 分支上:
Git 提示自动合并失败,需要我们来手动处理冲突。这时输入 cat file01 查看 file01 当前内容:
可以看到 Git 已经帮我们列出冲突产生的位置,并把不同分支上的内容都展示出来,以便我们处理冲突。输入 vi file01 来修改这个冲突:
这里我们修改 count 为 5,随后将这个修改提交:
最后输入 git-log 查看提交记录,发现已经成功处理了冲突,dev 分支也已经合并到 master 分支上。
在开发中,一般有如下分支使用原则和流程:
线上分支,主分支,中小规模项目作为线上运行的应用对应的分支。
是从 master 创建的分支,一般作为开发部门的主要开发分支,如果没有其他并行开发不同期上线要求,都可以在此版本进行开发,阶段开发完成后,需要合并到 master 分支,准备上线。
从 develop 创建的分支,一般是同期并行开发,但不同期上线时创建的分支,分支上的开发任务完成后合并到 devdelop 分支。
从 master 派生的分支,一般作为线上 bug 修复时使用,修复完成需要合并到 master、test(用于代码测试)、devdelop 分支。
master 分支是稳定运行的版本,一般是已经部署上线的版本,是跑在服务器(或其他设备)上的最终版本。开发任务主要是在 develop 上进行的,但并不是直接在 develop 分支上开发新功能,而是所有已经开发的代码都应该提交到 develop 分支上面。若想开发一个新功能,那么就在 devdelop 分支上最新的版本上创建一个 feature 分支,命名为 feature/功能,在这个 feature 分支上开发新的功能,开发完成后将代码合并到 develop 分支上。如果并行开发多个新功能,那么做法也是一样的,由其他开发者在 devdelop 上创建新的 feature 分支,最后将开发完的代码都合并到 devdelop 分支上。如果当前功能都已开发完毕,那么就可以将 devdelop 分支合并到 master 分支上形成一个 release 版本,这个 release 版本就是最终发布的稳定版。
需要注意的是,feature 分支是为了多个新功能的开发互不影响而临时创建的分支,当把 feature 分支合并到 devdelop 分支以后,这个临时的 feature 分支就没用了,所以要把这个分支删除掉。那么当 develop 分支开发完成后,develop 分支是不能删除的,master 分支和 develop 分支是固定的两个分支,都不能删除。
另外,在图中还有 hotfix 分支,这个分支是用来修复已经发布的版本中产生的 bug。比如图中 release2 版本中用户反馈了一个 bug,我们现在要去修复这个 bug,可肯定不能在 master 分支上直接修改,这会影响到所有的用户。这时我们可以 在当前版本上创建一个 hotfix 分支,在这个分支上进行一系列的修改、测试,最终确定 bug 已经修复后,再合并到 master 分支上形成下一个 release 版本。随后还要将 hotfix 分支合并到 devdelop 分支上,因为如果不合并到 develop 分支上,后续 develop 分支新功能开发完毕合并到 master 分支上时,就会丢失先前修复的提交,所以这里还要合并到 develop 分支上。
Git 快进模式(Fast-forward)是一种分支合并方式,当要合并的分支是当前分支的直接后继时,Git 会简单地将当前分支指针向前移动到目标分支的最新提交而不创建新的合并提交。
这么说太抽象了,还是看一个例子:
查看当前分支,日志显示当前有两个一模一样的分支:master 分支和 dev 分支。随后我们在 dev 分支上创建 file03 文件并提交:
再次查看提交日志,发现 dev 分支上只比 master 分支上多了一次提交,如果这时我们将 dev 分支合并到 master 分支上:
Git 会自动识别到 dev 分支上 master 分支的直接后继,即 master 分支上有的 dev 分支也都有,这时合并就不会产生冲突,就会触发 Git 的快进模式,即 Fast-forward 模式,Git 会简单地把当前分支指针指向 dev 分支的最新提交,这时 master 分支也就处于这个地方,而且不会产生以往合并分支时类似于小桥一样的结构。
前面我们所有的提交都是在本地仓库中进行的,如果想把代码备份到互联网中,那么就需要使用远程仓库来管理。远程仓库是指存储在网络上的 Git 仓库,主要用于团队协作和代码备份。
常用的远程仓库平台有:
本篇文章将采用 GitHub 平台作为示例,介绍远程仓库的配置以及代码管理。
Git 与 GitHub 的关系:Git 是一个版本控制系统,而 GitHub 是一个使用 Git 的工具和服务提供者。开发者可以在本地进行版本控制,然后将代码推送到 GitHub 上进行共享和协作。
此操作是先初始化本地库,然后与已创建的远程库进行对接。
git remote add <远端名称> <仓库路径>
比如:
回车后若没有提示错误就说明远程仓库连接成功
git remote远程仓库的名称为 origin
这里先省略掉 -f 和 --set-upstream 两个参数,则这个指令可以写成:git push origin master:master,表示将本地的 master 分支推送到远程仓库的 master 分支上。
这样就推送成功了,刷新 GitHub 中的仓库:
可以看到我们的远程仓库已经有内容了,并且和本地的 master 分支的内容一模一样。
比如在上面的例子中,本地分支和远端分支名都为 master,我们就可以省略为:git push origin master ,还是表示将本地的 master 分支推送到远程仓库的 master 分支上。
可以看到和上面的方式没什么区别,简化了一点而已。
-f 表示强制覆盖,就是说有冲突存在时,git 不允许直接 push,这时我们可以加上 -f 来强制覆盖远程仓库的代码。--set-upstream 表示将本地分支推送到远程的同时并且建立起本地的当前分支和远端分支的关联关系,这样后面再次推送时 Git 就可以根据这个关联关系来判断我们想推送到远端的哪个分支上,这时就可以只输 git push 来完成推送操作。比如:git push --set-upstream origin master
这样本地的 master 分支已经和远程的 master 分支关联上了。下次如果在本地 master 分支上想要往远程的 master 分支推送时只用输入 git push 指令。
git push 将 master 分支推送到已关联的远端分支。
和正常的指令效果一样,可以正常推送。
git branch -vv如果已经有一个远端仓库,我们可以直接克隆到本地
我们可以新建一个文件夹来克隆远程仓库:
在想要克隆的目录下右键打开 Git Bash,输入 git clone <仓库路径> <本地名称>,如果不指定目录就会自动新建一个目录,名称就是远程仓库的名称。等待一会就克隆成功了,它和我们本来的本地库和远程仓库的内容都是一模一样的。关掉刚刚克隆仓库的 Git Bash,因为这是在 hello-git 外面打开的 Git Bash 是操作不了 hello-git 这个库的,进入 hello-git 右键打开 Git Bash,输入 git-log,在刚刚推送的 Git Bash 中也输入 git-log:
可以看到基本一模一样,只不过我们的本地库多了一个 dev 分支而已。
有这么一个场景:两个人协作开发同一个项目,其中一个人开发完一个功能后将代码提交,另一个人想要拿到这个更新,是不是可以直接克隆整个远程仓库呢?这当然是可以的,不过克隆操作一般只会用到一次,在创建项目的时候才会用到。每次要拿到新的更新都克隆太过麻烦了,因为有可能整个项目很大,非常费时间。这就要用到抓取和拉取操作了。
git fetch [remote name] [branch name]
比如,我在原本的本地库中新建文件 file04 并提交:
看看新建之前的日志:
可以发现 git 将当前分支指针后移指向最新提交,这就是前面介绍的快进模式。我们将本地的修改推送到远端中去,就类似于一个快进模式的合并。
随后在克隆的仓库中通过 fetch 来拿到这个更新:
但是当前本地库还处于 add file03,本地的 master 分支中并没有 add file04 这个提交,说明 fetch 指令只会拿到更新,并不会把这个更新合并到本地分支。这时我们可以通过 merge 指令来将远端 master 分支合并到本地 master 分支上:
和另一个 Git Bash 中的日志一样,接下来看看拉取,可以直接抓取并合并。
git pull [remote name] [branch name]
在原始本地库中新建 file05 并推送:
在克隆库中拉取:
日志显示两个人的记录一模一样,比单纯的抓取方便多了。
在一段时间,A、B 用户修改了同一个文件,且修改了同一行位置的代码,此时会发生合并冲突。 A 用户在本地修改代码后优先推送到远程仓库,此时 B 用户在本地修订代码,提交到本地仓库后,也需要 推送到远程仓库,此时 B 用户晚于 A 用户,故需要先拉取远程仓库的提交,经过合并后才能推送到远端分支,如下图所示。
在 B 用户拉取代码时,因为 A、B 用户同一段时间修改了同一个文件的相同位置代码,故会发生合并冲 突。
远程分支也是分支,所以合并时冲突的解决方式也和解决本地分支冲突相同相同,在此不再赘述。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online