Git 从零基础到大神:安装、操作、分支与协作指南
Git 版本控制系统的核心知识。内容包括在 Ubuntu 下的安装配置、工作区暂存区与版本库的概念、文件增删改查及回退操作。深入讲解了分支管理策略,包括创建切换合并冲突解决及强制删除。同时涵盖远程仓库的克隆推送拉取、忽略文件配置及别名设置。最后通过多人协作场景演示了本地合并与 Pull Request 流程,帮助读者掌握团队协作开发技能。

Git 版本控制系统的核心知识。内容包括在 Ubuntu 下的安装配置、工作区暂存区与版本库的概念、文件增删改查及回退操作。深入讲解了分支管理策略,包括创建切换合并冲突解决及强制删除。同时涵盖远程仓库的克隆推送拉取、忽略文件配置及别名设置。最后通过多人协作场景演示了本地合并与 Pull Request 流程,帮助读者掌握团队协作开发技能。

以平台 Ubuntu 24.04 为例,安装 Git。
在终端中输入查看版本信息的命令:
root@iZbp16khlytibqc83gbmonZ:~# git --version
如果已经安装了 Git,会显示 Git 的版本信息:
git version 2.43.0
如果没有安装,则会提示找不到该命令:
Command 'git' not found, but can be installed with: apt install git Please ask your administrator.
在终端中输入以下命令:
root@iZbp16khlytibqc83gbmonZ:~# sudo apt-get install git -y
CentOS7 下安装 Git 命令:sudo yum install -y git
Windows 下官方下载地址:https://git-scm.com/
命令输入后,就会自动去下载对应的包,再通过查看版本信息命令来看是否已经成功安装
git version 2.43.0
如果想要卸载系统中的 Git,可以输入以下命令:
sudo apt-get remove git -y
Git 是版本控制器,可以追踪和管理电脑或者服务器上的文件,但是不能是任意位置的文件,必须是 Git 管理的仓库中,所以我们要想对⽂件进⾏版本控制,就必须先创建⼀个仓库出来。
仓库是进⾏版本控制的⼀个⽂件⽬录,首先要先创建一个文件目录
root@iZbp16khlytibqc83gbmonZ:~# mkdir gitcode
注意命令要在⽂件⽬录下执⾏,我们要进入目录
root@iZbp16khlytibqc83gbmonZ:~# cd gitcode/
执行 Git 本地仓库对应的命令,就可以在当前目录下创建一个本地仓库
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git init
会出现一个提示,在此目录下创建了一个隐藏文件目录.git,代表你的本地仓库 已经创建成功了
Initialized empty Git repository in /root/gitcode/.git/
输入 ls -a 命令,即可查看文件目录下隐藏文件目录.git
root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls -a .git
我们可以查看一下此隐藏目录
root@iZbp16khlytibqc83gbmonZ:~/gitcode# tree .git
注意:
不要⼿动修改这个⽬录⾥⾯的⽂件,不然改乱了,就把 Git 仓库给破坏了
安装 Git 后必须设置用户名和邮箱,因为 Git 每次提交代码都需要记录提交者的身份,用来标识是谁做的修改,方便版本追溯和团队协作,不设置就无法正常提交代码。
配置用户名:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config user.name "Your Name"
配置邮箱:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config user.email "[email protected]"
查看本地仓库配置后的配置列表,查看是否配置成功
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config -l core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true user.name=Your Name [email protected]
最后两项就是我们配置的用户名和邮箱,表示配置成功了,前面几行配置是我们创建仓库时默认给我配置的配置项
删除配置项:
配置项也可以删除,这里以删除用户名为例
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config --unset user.name root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config -l core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true [email protected]
通过查看配置列表,用户名已经没有了,已经删除了
全局配置:
我们在一台服务器上不止可以创建一个本地仓库,我们可以在配置项上添加--global,使得整个服务器所有 Git 仓库都用这个配置
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config --global user.name "Your Name" root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config --global user.email "[email protected]" root@iZbp16khlytibqc83gbmonZ:~/gitcode# git config -l user.name=Your Name [email protected] core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true
注意:
用全局配置的,不能直接git config --unset命令来删除,得加上--global比如说删除全局配置用户名:
git config --global --unset user.name "Your Name"
先提一个问题,如果我在仓库目录下创建一个了文件,你们觉得,Git 能否直接管理这个文件呢?
先说答案:不能! 奇怪了,不是说了放入本地仓库的文件不都是可以被 Git 管理的吗,这不是已经放入本地仓库了,为啥这个文件不能被管理呀,这里就要提出这几个概念了⼯作区、暂存区、版本库。
• ⼯作区:是在电脑上你要写代码或⽂件的⽬录。
• 暂存区:英⽂叫stage或index。⼀般存放在把暂存区有时也叫作索引(index)。
• 版本库:⼜名 仓库 ,英⽂名 .git ⽬录下的 index⽂件(.git/index)中,我们 repository。⼯作区有⼀个隐藏⽬录.git,它不算⼯作区,⽽是 Git 的版本库。这个版本库⾥⾯的所有⽂件都可以被 Git 管理起来,每个⽂件的修改、删除,Git 都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以'还原'。
ReadMe 所在的此目录并不是本地仓库,真正的本地仓库(版本库)而是隐藏的文件目录.git,而 ReadMe 存在的区域为工作区,所以 ReadMe 没有在本地仓库,自然 Git 不能管理这个文件,只是相当于在工作区添加了文件。
• 图中左侧为⼯作区,右侧为版本库。Git 的版本库⾥存了很多东西,其中最重要的就是暂存区。
• 在创建 Git 版本库时,Git 会为我们⾃动创建⼀个唯⼀的 master分⽀,以及指向 master 的⼀个指针叫 HEAD。
• 当对⼯作区修改(或新增)的⽂件执⾏git add 命令时,暂存区⽬录树的**⽂件索引会被更新**。
• 当执⾏提交操作git commit 时,master 分⽀会做相应的更新,可以简单理解为暂存区的⽬录树才会被真正写到版本库中
注意:
不允许手动将工作区的文件移动到 版本库.git 下,这样子会破坏本地库,必须要通过使⽤git add和git commit命令才能将⽂件添加到仓库中进⾏管理
将文件添加到本地仓库:
git add命令将ReadMe⽂件添加到暂存区root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls -a .git root@iZbp16khlytibqc83gbmonZ:~/gitcode# touch ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# vim ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add ReadMe
git add [file1] [file2] ... :添加⼀个或多个⽂件到暂存区git add . :添加当前⽬录下的所有⽂件改动到暂存区git add [dir]:添加指定⽬录到暂存区,包括⼦⽬录git commit将暂存区内容添加到本地仓库中root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "提交的第一个文件"[master (root-commit) ed2bd0a] 提交的第一个文件 1 file changed, 2 insertions(+) create mode 100644 ReadMe
git commit -m "你这次提交代码的【备注 / 说明】":提交暂存区全部内容到本地仓库中git commit [file1] [file2] ... -m "你这次提交代码的【备注 / 说明】":提交暂存区的指定⽂件到仓库区注意:git commit 后⾯的 -m 选项要跟上描述本次提交的备注 / 说明,由⽤⼾⾃⼰完成,这部分内容绝对不能省略,并要好好描述,是⽤来记录你的提交细节,是给我们⼈看的
git log命令我们可以看到截至为止的历史提交记录:root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log commit ed2bd0a99003808198cfcfae97925b5ef728ac79 (HEAD -> master) Author: hr <[email protected]> Date: Sat Mar 14 16:25:03 2026 +0800 提交的第一个文件
如果简化记录内容可以通过加选项参数--pretty=oneline:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --pretty=oneline ed2bd0a99003808198cfcfae97925b5ef728ac79 (HEAD -> master) 提交的第一个文件
commit id:
Git 会把你的每次提交、每个文件都加密存放在 .git/objects/ 文件夹里
加密后会生成一长串 40 位字符 → 这就是 commit id
Git 把这 40 位字符分成两部分:
前 2 位 → 当 文件夹名
后 38 位 → 当 文件名commit id 是 .git/objects/ 里对应文件的名字,Git 通过这个 id 找到并读取你的提交数据
Git ⽐其他版本控制系统设计得优秀,因为Git 跟踪并管理的是修改,⽽⾮⽂件。
什么是修改?⽐如你新增了⼀⾏,这就是⼀个修改,删除了⼀⾏,也是⼀个修改,更改了某些字符,也是⼀个修改,删了⼀些⼜加了⼀些,也是⼀个修改,甚⾄创建⼀个新⽂件,也算⼀个修改。
我们来修改一下文件:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git root@iZbp16khlytibqc83gbmonZ:~/gitcode# vim ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update
我们知道仓库和工作区的 ReadMe 是不一样的,我们可以通过git status命令⽤于来查看在你上次提交之后是否有对⽂件进⾏再次修改,来查看仓库的状态:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory) modified: ReadMe no changes added to commit (use "git add" and/or "git commit -a")
如果想查看文件被修改了啥,我们可以使用git diff命令,它是⽤来显⽰暂存区和⼯作区⽂件的差异
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git diff ReadMediff--git a/ReadMe b/ReadMe index 697685a..ec01bd5 100644 --- a/ReadMe +++ b/ReadMe @@ -1,2 +1,3 @@ hello git +update
git diff [file]:⽤来显⽰暂存区和⼯作区⽂件的差异git diff HEAD -- [file]:查看版本库和⼯作区⽂件的区别
当我们将修改提交到暂存区后,再次查看仓库状态:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: ReadMe
提示有文件已经进入暂存区,准备好被提交。我们提交后再次查看仓库状态
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "modify ReadMe"[master a5e5b49] modify ReadMe 1 file changed, 1 insertion(+) root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master nothing to commit, working tree clean
提示已经没有什么能够提交了,工作区是干净的
Git 能够管理⽂件的历史版本,这也是版本控制器重要的能⼒。如果有⼀天你发现之前前的⼯作做的出现了很⼤的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本回退的功能了。
git reset 命令用于版本回退可以指定退回某⼀次提交的版本。要解释⼀下'回退'本质是要将版本库中的内容进⾏回退,⼯作区或暂存区是否回退由命令参数决定。
git reset [--soft | --minxed | --hard] commit-ID--mixed :为默认选项,使⽤时可以不⽤带该参数。该参数将版本库和暂存区的内容回退为指定提交版本内容,⼯作区⽂件保持不变。--soft: 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本--hard: 参数将暂存区与⼯作区和版本库都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重准备 v1 和 v2 两个版本的 ReadMe 文件
| 版本 | v1 | v2 |
|---|---|---|
| 内容 | git v1 | git v2 |
执行 git reset 加上对应参数后各个区域内容:
| 参数 | 工作区 | 暂存区 | 版本库 |
|---|---|---|---|
| –soft | git v2 | git v2 | git v1 |
| –mixed | git v2 | git v1 | git v1 |
| –hard | git v1 | git v1 | git v1 |
举个列子:以使用 --hard 为例
root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls file1 ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --pretty=oneline 94c62fe69c0ba0709302f71cd9c226c2fced053c (HEAD -> master) 提交的第三个文件 a5e5b49a4f3cd1c55a11c7a548980ebe445eca62 modify ReadMe ed2bd0a99003808198cfcfae97925b5ef728ac79 提交的第一个文件
通过查看历史提交记录,从上到下依次为提交时间,通过拿到最早的 commit id 回退到最早的提交
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git reset --hard ed2bd0a99003808198cfcfae97925b5ef728ac79 HEAD is now at ed2bd0a 提交的第一个文件 root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --pretty=oneline ed2bd0a99003808198cfcfae97925b5ef728ac79 (HEAD -> master) 提交的第一个文件
通过打印 ReadMe 文件内容和查看历史提交记录,可知现在已经回退到最早版本
同时如果后悔回退后,仍然可以再次通过git reset 命令加指定的回退版本(commit id)来回退
root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --pretty=oneline ed2bd0a99003808198cfcfae97925b5ef728ac79 (HEAD -> master) 提交的第一个文件 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git reset --hard 94c62fe69c0ba0709302f71cd9c226c2fced053c HEAD is now at 94c62fe 提交的第三个文件 root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls file1 ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --pretty=oneline 94c62fe69c0ba0709302f71cd9c226c2fced053c (HEAD -> master) 提交的第三个文件 a5e5b49a4f3cd1c55a11c7a548980ebe445eca62 modify ReadMe ed2bd0a99003808198cfcfae97925b5ef728ac79 提交的第一个文件
通过打印 ReadMe 文件内容和查看历史提交记录,可知现在已经回退到指定版本
如果通过某种情况,发现 commit id 的记录不见了,我们可以通过git reflog命令来找回,该命令⽤来记录本地的每⼀次命令
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git reflog 94c62fe (HEAD -> master) HEAD@{0}: reset: moving to 94c62fe69c0ba0709302f71cd9c226c2fced053c ed2bd0a HEAD@{1}: reset: moving to ed2bd0a99003808198cfcfae97925b5ef728ac79 94c62fe (HEAD -> master) HEAD@{2}: commit: 提交的第三个文件 a5e5b49 HEAD@{3}: commit: modify ReadMe ed2bd0a HEAD@{4}: commit (initial): 提交的第一个文件 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git reset --hard 94c62fe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --pretty=oneline 94c62fe69c0ba0709302f71cd9c226c2fced053c (HEAD -> master) 提交的第三个文件 a5e5b49a4f3cd1c55a11c7a548980ebe445eca62 modify ReadMe ed2bd0a99003808198cfcfae97925b5ef728ac79 提交的第一个文件
版本回退的速度为什么很快?因为它只修改分支文件里的 commit id,不移动任何代码,只是切换指针指向
一共有三种情况:想撤销的'xxx code'代码分存在于不同位置
| 工作区 | 暂存区 | 版本库 | 解决方法 | 说明 |
|---|---|---|---|---|
| xxx code | 1.手动撤销—不推荐,容易出错 2. git checkout -- [file] —推荐 | ⽂件回到最近⼀次 add 或 commit 时的状态 | ||
| xxx code | xxx code | 1.git reset --mixed HEAD [file] 后继续git checkout -- [file] 2. git reset --hard HEAD [file] | 1 方法是在你还没有 commit 到版本库里利用 mixed 版本回退暂存区内容,再 git checkout 回退工作区内容。(HEAD 表示回退到当前版本,回到上一个版本 HEAD^ 以此类推加上^) 2 方法本质上是利用 hard 的版本回退来撤销修改 | |
| xxx code | xxx code | xxx code | git reset --hard HEAD^ | 回退到上⼀个版本,但是有个前提条件还没有把⾃⼰的本地版本库推送到远程(commit 之后没有 push) |
在 Git 中,删除也是⼀个修改操作,所以我们可以直接删除工作区中文件
root@iZbp16khlytibqc83gbmonZ:~/gitcode# rm file1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory) deleted: file1 no changes added to commit (use "git add" and/or "git commit -a")
此时,⼯作区和版本库就不⼀致了,要删⽂件,⽬前除了要删⼯作区的⽂件,还要清除版本库的⽂件
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add file1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "delete file1"[master 486fd34] delete file1 1 file changed, 1 deletion(-) delete mode 100644 file1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# ls ReadMe
但是这样子太麻烦了要进行好几步操作,还容易误删,Git 提供了一种删除命令git rm
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git rm file1 rm'file1' root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) deleted: file1
仅仅再需要commit一次就可以了,git rm已经替我们完成了对工作区和暂存区的删除
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "delete file1"[master 9123342] delete file1 1 file changed, 1 deletion(-) delete mode 100644 file1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master nothing to commit, working tree clean
在版本回退⾥,你已经知道,每次提交,Git 都把它们串成⼀条时间线,这条时间线就可以理解为是⼀个分⽀。截⽌到⽬前,只有⼀条时间线,在 Git⾥,这个分⽀叫主分⽀,即 master 分⽀
再来理解⼀下 HEAD,HEAD 严格来说不是指向提交,⽽是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分⽀。
通过查看当前的版本库,我们也能清晰的理出思路:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/HEAD ref: refs/heads/master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/refs/heads/master 912334249d8315f1ba88953158a819c913c1e5e8 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --pretty=oneline 912334249d8315f1ba88953158a819c913c1e5e8 (HEAD -> master) delete file1 94c62fe69c0ba0709302f71cd9c226c2fced053c 提交的第三个文件 a5e5b49a4f3cd1c55a11c7a548980ebe445eca62 modify ReadMe ed2bd0a99003808198cfcfae97925b5ef728ac79 提交的第一个文件
我们可以通过git branch命令查看当前本地所有分支
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch* master
当我们创建本地仓库时,Git 会为我们自己创建一个 master 主分支
HEAD 可以指向其他分支,被 HEAD 指向的分支才是当前的工作分支,这里的 HEAD 是指向 master 的,所以之前所有的 add 和 commit 都是在 master 主分支上进行提交的
在这⾥我们再来创建第⼀个⾃⼰的dev 分⽀,只需要git branch 命令后面加上分支名称dev
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/HEAD ref: refs/heads/master
master 前面有*,说明现在 HEAD 还是指向 master 分支的,通过 cat .git/HEAD 也可以验证
既然创建了 dev 分支,那这个分支的内容是什么呢,我们可以查看一下
root@iZbp16khlytibqc83gbmonZ:~/gitcode# tree .git
通过⽬录结构发现 dev 和 master 指向同⼀个修改,也就是说创建的 dev 是基于最新的一次提交创建的
如何将 master 切换到 dev 分支呢,Git 提供了git checkout命令,来切换分支
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout dev Switched to branch 'dev' root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch * dev master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/HEAD ref: refs/heads/dev
dev 前面出现了*,cat .git/HEAD 也验证了,现在指向了 dev 分支
既然已经切换到 dev 分支了,那我们修改 ReadMe⽂件,并进⾏⼀次提交操作,在切换到 master 分支看看会有什么效果
root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update root@iZbp16khlytibqc83gbmonZ:~/gitcode# vim ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev dev dev root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "md ReadMe"[dev 034add1] md ReadMe 1 file changed, 1 insertion(+)
dev 分⽀的⼯作完成,我们就可以切换回 master 分⽀:
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout master Switched to branch 'master' root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update
可以发现,ReadMe 中修改的内容不见了,切换 dev 分支查看是否还存在
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout dev Switched to branch 'dev' root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev dev dev
在 dev 分支上修改的内容还是存在的,我们再看看各个分支指向
root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/refs/heads/dev 034add12801fd3f42a2e312e341c42071f0fb1b4 root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/refs/heads/master 912334249d8315f1ba88953158a819c913c1e5e8 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git cat-file -p 034add12801fd3f42a2e312e341c42071f0fb1b4 tree ed29087415cd1b65518cf761fecc8fd030924813 parent 912334249d8315f1ba88953158a819c913c1e5e8 author hr <[email protected]> 1773543349 +0800 committer hr <[email protected]> 1773543349 +0800 md ReadM
很明显,两者指向的提交是不⼀样的,且通过 git cat-file -p 中 parent 知道 dev 分支上一个提交的指向和 master 当前提交的指向是一样的看到这⾥就能明⽩了,因为我们是在 dev 分⽀上提交的,⽽ master 分⽀此刻的提交点并没有变,此时的状态如图如下所⽰
当切换到 master 分⽀之时,HEAD 就指向了 master,就看不到提交了
为了能在 master 上也能看到新的提交,我们需要用git merge命令来合并分支。
要将 dev 分支合并到 master 分支上,首先要切换到 master 分支
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch * dev master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/refs/heads/dev 034add12801fd3f42a2e312e341c42071f0fb1b4 root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev dev dev root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch * dev master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout master # 切换到 master 上进⾏合并 Switched to branch 'master' root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/refs/heads/master 912334249d8315f1ba88953158a819c913c1e5e8 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git merge dev # 合并 dev 分⽀ Updating 9123342..034add1 Fast-forward ReadMe | 1 + 1 file changed, 1 insertion(+) root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev dev dev root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat .git/refs/heads/master 034add12801fd3f42a2e312e341c42071f0fb1b4
提示 ReadMe 文件发生修改
master 指向的最新提交指向和 dev 最新提交指向一样了,示意图如下
如果觉得这个分支没有用了,而且又占资源,我们可以使用git branch -d 来删除这个分支,注意不能删除当前处在的分支
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch -d dev Deleted branch dev (was 034add1). root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch* master
当我们在主分支和其他分支上都进行了修改,再进行合并分支时候就可能会遇到代码冲突的问题。
示例演示:
在 dev1 分⽀下修改 ReadMe ⽂件,更改⽂件内容如下,并进⾏⼀次提交
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout -b dev1 Switched to a new branch 'dev1' root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch * dev1 master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev dev dev root@iZbp16khlytibqc83gbmonZ:~/gitcode# vim ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev1 dev1 dev1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch dev1 Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "md ReadMe:dev1 dev1 dev1"[dev1 1351a58] md ReadMe:dev1 dev1 dev1 1 file changed, 1 insertion(+), 1 deletion(-) root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch dev1 nothing to commit, working tree clean
切换⾄ master 分⽀,观察 ReadMe ⽂件内容
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout master Switched to branch 'master' root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev1 * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev dev dev
内容仍然是原先,复合逻辑
此时在 master 分⽀上,我们对 ReadMe⽂件再进⾏⼀次修改,并进⾏提交
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev1 * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update dev dev dev root@iZbp16khlytibqc83gbmonZ:~/gitcode# vim ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "md ReadMe:master master master"[master 0bd1cff] md ReadMe:master master master 1 file changed, 1 insertion(+), 1 deletion(-) root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master nothing to commit, working tree clean root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master
经过上述操作,master 和 dev1 都有了新的提交,如图所示
这种情况下,Git 只能试图把各⾃的修改合并起来,看看效果
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev1 * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git merge dev1 Auto-merging ReadMe CONFLICT (content): Merge conflict in ReadMe Automatic merge failed; fix conflicts and then commit the result.
合并失败
提示:自动合并 ReadMe 文件 冲突(内容):ReadMe 文件中的合并冲突 自动合并失败;请先解决冲突,然后提交结果。
发现 ReadMe 文件发生冲突,直接查看 ReadMe 文件
root@iZbp16khlytibqc83gbmonZ:~/gitcode# vim ReadMe hello git update <<<<<<< HEAD master master master ======= dev1 dev1 dev1 >>>>>>> dev1 ~
此时只能通过我们手动人为的进行解决,到底是要保留或删除哪行内容,这里保留 master,不要忘了要再次提交
root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git status On branch master All conflicts fixed but you are still merging.(use "git commit" to conclude merge) root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "merge dev1"[master f25393a] merge dev1
到这⾥冲突就解决完成,此时的状态变成了如图所式:
也可以通过 Git 提供的查看分支方式:git log --graph --pretty=oneline --abbrev-commit
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "merge dev1"[master f25393a] merge dev1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --graph --pretty=oneline --abbrev-commit* f25393a (HEAD -> master) merge dev1 |\ |* 1351a58 (dev1) md ReadMe:dev1 dev1 dev1 *| 0bd1cff md ReadMe:master master master |/* 034add1 md ReadMe * 9123342 delete file1 * 94c62fe 提交的第三个文件 * a5e5b49 modify ReadMe * ed2bd0a 提交的第一个文件
First-forword(ff) 模式:直接使用git merge合并,Git 合并时的一种'偷懒'模式,直接把分支指针往前挪,不生成新 commit
举个列子:新建一个 dev1 分支,修改内容并提交后,切换 master 合并分支,查看 log
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev1 * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout dev1 Switched to branch 'dev1' root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master root@iZbp16khlytibqc83gbmonZ:~/gitcode# vim ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master dev1 dev1 dev1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git add ReadMe root@iZbp16khlytibqc83gbmonZ:~/gitcode# git commit -m "md RM:dev1 dev1 dev1"[dev1 704e72d] md RM:dev1 dev1 dev1 1 file changed, 1 insertion(+) root@iZbp16khlytibqc83gbmonZ:~/gitcode# git checkout master Switched to branch 'master' root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git merge dev1 Updating 8dae404..704e72d Fast-forward ReadMe | 1 + 1 file changed, 1 insertion(+) root@iZbp16khlytibqc83gbmonZ:~/gitcode# cat ReadMe hello git update master master master dev1 dev1 dev1 root@iZbp16khlytibqc83gbmonZ:~/gitcode# git log --graph --pretty=oneline --abbrev-commit* 704e72d (HEAD -> master, dev1) md RM:dev1 dev1 dev1 * 8dae404 md RM* 4dcea7f md ReadMe * f25393a merge dev1 |\ |* 1351a58 md ReadMe:dev1 dev1 dev1 *| 0bd1cff md ReadMe:master master master |/* 034add1 md ReadMe * 9123342 delete file1 * 94c62fe 提交的第三个文件 * a5e5b49 modify ReadMe * ed2bd0a 提交的第一个文件

在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提交到底是 merge 进来的还是正常提交的
no-ff 模式:使用git merge --no-ff -m 进行合并,强制生成一个新的「合并 commit」,保留分支合并的痕迹,不会把指针直接平移

在实际开发中,要求 master 分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯⼲活,所以我们⼲活都在 dev 分⽀。
假设当我们在开发 dev2 时,还没有提交,发现了 master 出现了 bug 怎么办?按照开发要求我们肯定不能在 master 上直接修改,所以我们必须要在新建一个 fix_bug 分支用来修复 bug,但是直接切换分支,会导致 dev 工作区的开发内容出现在 master 的工作区中,我们又不想使得 master 内容发生改变。
此时的状态图为:

我们需要用到 Git 提供了git stash 命令,可以将当前的⼯作区信息进⾏储藏,被储藏的内容可以在将来某个时间恢复出来,可以放⼼地创建分⽀来修复 bug,等待 fix_bug 分支修复好 bug 后,完成合并,删除 fix_bug 分支,此时工作区内容肯定是干净的,回到 dev2 分支使用git stash pop命令来从 stash 存储区恢复回到工作区。
此时的状态图为:

⼯作区信息存到了 refs/stash 目录下
我们继续再 dev2 进行开发,直到 dev2 开发完成后,进行合并,但是将 dev2 合并到 master 后可能会出现合并冲突,这就需要我们去解决冲突,但是我们⽆法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到此时的状态为 master 上。
此时的状态图为:

所以最好的方法还是将 master 合并到 dev2 中,将冲突的内容再 dev2 中修复,这样子不会影响到 master
此时的状态图为:

待冲突解决完后,再 dev2 合并到 maste

在开发过程中,项目经理向你提出了一个功能要开发,你创建一个分支来专门写新功能,当你开发到一半,项目经理又说算了这个功能不要了,那肯定要把这个分支删除但是直接git branch -d是不会成功的,如果分支没合并,Git 会拒绝删除并报错
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch -d dev3 error: The branch 'dev3' is not fully merged.If you are sure you want to delete it, run 'git branch -D dev3'
Git 提供了git branch -D命令来强制删除
root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch dev3 * master root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch -D dev3 Deleted branch dev3 (was cd2f149). root@iZbp16khlytibqc83gbmonZ:~/gitcode# git branch * master
之前我们在本地服务器上敲 git add、git commit命令 等的这个仓库,叫做 本地仓库,有很多弊端比如:只存在你这台电脑里,别人看不到,电脑坏了,代码可能就没了,只能你一个人用
而远程仓库 = 放在互联网服务器上的 Git 仓库。 它不是你本地的,而是放在别人的服务器上(比如 GitHub、Gitee、公司 Git 服务器),有很多优点比如:代码备份,多人协作,随时随地开发等等。
新建远程项⽬仓库(这边只进行部分介绍,更多不清楚可以参考帮助中心):
进入官网,注册一个账号,点击右上角按钮

是按照自己的需求创建就可以了,这里不过多的赘述

创建好后,查看此远程仓库,可以看到之前学过的分支,只不过这是远程的,且只有一个 master 分支

Issues 是项目任务与协作管理核心工具,用于统一追踪 Bug、需求、任务,支持分配、标签、里程碑与看板,还能关联代码提交和 PR,形成开发闭环

如果发现了 bug,可以通过 Issues 来联系于仓库管理者或者仓库人员

在实际开发中,不让任何人随便改主干代码(master),不会随意的将 dev 分支的合并到主分支 master,所以就需要Pull Request,向管理员申请把我的代码,合并到你的仓库里,也就是提供审核的作用

可以直接将操作要合并的分支
打开远端仓库的从仓库中找到:选择'克隆/下载'获取远程仓库链接,可获取远端仓库的链接

可以看到有四种链接,其中 SSH 协议和 HTTPS 协议是 Git 最常使⽤的两种数据传输协议,将链接放到git clone命令后。
git clone HTTPS 链接root@iZbp16khlytibqc83gbmonZ:~# git clone https://gitee.com/hrKiley/remove-gitcode.git Cloning into 'remove-gitcode'... remote: Enumerating objects: 7, done. remote: Counting objects: 100% (7/7), done. remote: Compressing objects: 100% (7/7), done. remote: Total 7 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) Receiving objects: 100% (7/7), done. root@iZbp16khlytibqc83gbmonZ:~# ls gitcode remove-gitcode root@iZbp16khlytibqc83gbmonZ:~# cd remove-gitcode/ root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# ls -a .git .gitee README.en.md README.md
注意:
不能再任何的本地仓库目录下克隆远程仓库
origin 为远程仓库的默认名字,我们可以通过git remote命令来查看
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git remote origin
如果想查看的更详细,使用git remote -v命令
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git remote -v origin https://gitee.com/hrKiley/remove-gitcode.git (fetch) origin https://gitee.com/hrKiley/remove-gitcode.git (push)
(fetch)表示:拉代码用这个地址 https://gitee.com/hrKiley/remove-gitcode.git
(push)表示:传代码用这个地址 https://gitee.com/hrKiley/remove-gitcode.git
git clone SSH 地址先在本地服务器下,看看有没有.ssh 目录下有没有id_rsa(私钥) 和id_rsa.pub(公钥) 这两个⽂件,如果没有,可以通过ssh-keygen -t rsa -C "输⼊⾃⼰的 gitee 上配置的邮箱"来创造这两个文件,复制id_rsa.pub(公钥)内容到公钥框内,点击确定后即可,最后克隆方式和 HTTP 协议类似:git clone SSH 地址

成功将远程仓库 clone 到本地后可以开始修改,但是修改的内容远程仓库不知道,所以我们得通过 push 将本地的内容推送到远程仓库,注意:配置项 name 和 e-mail 要和 gitee 上的保持一致。
举个例子:推送 file 文件到远程仓库。
新增加 file.txt 文件,执行add 和 commit
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch * master root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# touch file.txt root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# vim file.txt root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat file.txt create file root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git add file.txt root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git commit -m "create file"[master 4786ad7] create file 1 file changed, 1 insertion(+) create mode 100644 file.txt root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git status On branch master Your branch is ahead of 'origin/master' by 1 commit.(use "git push" to publish your local commits) nothing to commit, working tree clean
可以看出 push 不是笼统地'推到仓库',而是推到 → 远程仓库里的某个具体分支,所以推送本质就是本地仓库的分支和远程仓库分支的交互
执行push命令:git push <远程主机名> <本地分⽀名>:<远程分⽀名>
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git push origin master:master Username for'https://gitee.com': hrKiley Password for'https://[email protected]': Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 2 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 274 bytes | 274.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag 45440bb8 To https://gitee.com/hrKiley/remove-gitcode.git 22577a3..4786ad7 master -> master
用 HTTPS 协议需要每次输入账号和必须输⼊⼝令,SSH 协议则是不⽤每⼀次推送都输⼊密码
打开远程仓库,代码已经被推送⾄远端了


当克隆远程仓库服务器不止一台时,假设有一台服务器也执行了 push 操作,此时远程仓库的内容就比自己本地的要新,此时我们就可以执行 pull 操作,来拉取远程仓库。
举个列子:
我们可以通过直接编辑远程仓库的文件来模拟,来让远程仓库比本地仓库新

执行pull命令:git pull <远程主机名><远程分⽀名>:<本地分⽀名>
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git pull origin master:master remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (3/3), 957 bytes | 957.00 KiB/s, done.From https://gitee.com/hrKiley/remove-gitcode 4786ad7..e4931b9 master -> master 4786ad7..e4931b9 master -> origin/master warning: fetch updated the current branch head. fast-forwarding your working tree from commit 4786ad782154384f9b005ce959cd7b82720d4456. Already up to date.
pull 其实帮我们做了两个动作 1.拉取远程分⽀ 2.并与当前分⽀进⾏合并
如果有不想提交到远端的文件,自己一个一个改又太麻烦了,我们可以在 Git⼯作区的根⽬录下创建⼀个特殊的.gitignore ⽂件,然后在文件里添加要忽略的文件名,这个文件能让 Git 知道有些⽂件不想或者不应该提交到远端。
举个例子:我想忽略.so 和.ini 结尾所有⽂件
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# touch s.so root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# touch i.ini root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# ls file.txt i.ini README.en.md README.md s.so root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# vim .gitignore root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# ls -a file.txt .git .gitee .gitignore i.ini README.en.md README.md s.so root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat .gitignore# 可以直接写文件名*.so *.ini
.so、.ini 中*表示忽略后缀名为 so、ini 的文件
通过git status命令来检验.gitignore ⽂件是否生效
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git status On branch master Your branch is up to date with 'origin/master'. Untracked files: (use "git add <file>..." to include in what will be committed).gitignore no changes added to commit (use "git add" and/or "git commit -a") root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git add . root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: .gitignore
很明显,.so 和.ini 结尾所有⽂件被忽略了,工作区只有
.gitignore文件
如果我们想将被忽略的文件中,某个文件不被忽略可以使用git add -f 文件名命令,或者在.gitignore文件中!在不想忽略的文件名前加上!。
举个例子:使得 b.so 文件不在被忽略。
.gitignore文件中不想忽略的文件名前加上!root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# vim .gitignore root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat .gitignore # 可以直接写文件名*.so *.ini !s.so root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: .gitignore Untracked files: (use "git add <file>..." to include in what will be committed) s.so
git add -f 文件名命令root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# ls -a file.txt .git .gitee .gitignore i.ini README.en.md README.md s.so root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat .gitignore # 可以直接写文件名*.so *.ini root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: .gitignore root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git add -f s.so root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: .gitignore new file: s.so
有时候我们可能会忘记该文件是否被忽略,我们可以使用git check-ignore -v 文件名 命令检查
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git check-ignore -v a.so.gitignore:3:*.so a.so
得知.gitignore 的第 3⾏规则忽略了该⽂件
如果你觉得某些命令太长了,Git 给我们提供了修改别名的方法。
比如说你想把git status变成git st,命令操作如下
git config --global alias.st status
–global 之前学到过,就是表示修改覆盖本机全部仓库
alias.'你想换成的命令别名',当然 status 命令还是可以正常用的
什么是标签呢,你可以理解为你平时看书看到某个重要部分加个书签做个记号,标签也就给代码打个'版本记号'。
直接通过git tag 标签名就可以打个新标签
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v1.0
⽤命令git tag 查看所有标签
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v1.0
标签是默认打到最新得一次提交上,当然也可以打到历史提交,只需要找到你想打标签得历史 commit id,使用git tag 标签名 [commit id]命令
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git log commit e69a90453c0d6f08020d309ea748a57f122e9800 (HEAD -> master, tag: v1.0) Author: hrKiley <[email protected]> Date: Mon Mar 16 16:51:34 2026 +0800 测试忽略特殊文件 commit e4931b90148380961d2f4612bf38bbef6e6f7a56 (origin/master, origin/HEAD) Author: 好人 <[email protected]> Date: Sun Mar 15 13:50:05 2026 +0000 update file.txt. Signed-off-by: 好人 <[email protected]> root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.9 e4931b90148380961d2f4612bf38bbef6e6f7a56 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.9 v1.0
注意:
标签不是按时间顺序列出,⽽是按字⺟排序的
如果你觉得这样还不够形象,Git 还提供给我们给标签提供描述,使用git tag -a 标签名 -m "标签描述" [commit_id]命令,配合git show 标签名,更详细得查看标签信息
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.8 -m "important tag:XX" 4786ad782154384f9b005ce959cd7b82720d4456 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.8 v0.9 v1.0 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git show v0.8 tag v0.8 Tagger: hrKiley <[email protected]> Date: Mon Mar 16 17:26:14 2026 +0800 important tag:XX commit 4786ad782154384f9b005ce959cd7b82720d4456 (tag: v0.8) Author: hrKiley <[email protected]> Date: Sun Mar 15 21:10:55 2026 +0800 create file diff--git a/file.txt b/file.txt new file mode 100644 index 0000000..ad80c42 ---/dev/null +++ b/file.txt @@ -0,0 +1 @@ +create file
删除标签很简单,使用git tag -d 标签名命令即可删除标签
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.8 v0.9 v1.0 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag -d v1.0 Deleted tag 'v1.0'(was e69a904) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.8 v0.9
标签都只存储在本地,可删除,也是可以推送到远程,使用git push 远程主机名 标签名
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.8 v0.9 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git push origin v0.8 Username for'https://gitee.com': hrKiley Password for'https://[email protected]': Enumerating objects: 1, done. Counting objects: 100% (1/1), done. Writing objects: 100% (1/1), 165 bytes | 165.00 KiB/s, done. Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag 404795a5 To https://gitee.com/hrKiley/remove-gitcode.git *[new tag] v0.8 -> v0.8
推送成功后可以在远程仓库看见

可以看到设置得标签名,描述等等
如果想要推送的标签很多,也可以使用git push 远程主机名 标签名 --tags命令一次性全部推送
推送过的远程标签页也可以删除,两个步骤。
举个列子:删除推送远程标签 v0.8。
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag -d v0.8 Deleted tag 'v0.8'(was 25f8881) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.9
git tag 远程主机名 :标签名root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag -d v0.8 Deleted tag 'v0.8'(was 25f8881) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git tag v0.9 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git push origin :v0.8 Username for'https://gitee.com': hrKiley Password for'https://[email protected]': remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag f54d628d To https://gitee.com/hrKiley/remove-gitcode.git -[deleted] v0.8
来到远程仓库(码云)可以看到推送过的标签已经被删除

学到这里想必大家对 Git 理解和使用应该得心应手了吧,但是实际开发中可不是自导自演,大多数都是多⼈协作开发,所以这个章节主要来模拟实现多⼈协作开发,让你以后跟团队协作,完全不慌。
因为是模拟实现多人协作开发,我们需要两个用户,由于一直演示的是部署云服务 Ubuntu 系统,所以就以一个为 Ubuntu 用户,另一个用本地电脑 win 用户为例:
远程仓库只有 master 主分⽀,我们都知道实际开发中是不能直接在 mater 中开发的,所以在 gitee 上新建 dev 远程分⽀供来我们使⽤

root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch * master root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch -r origin/HEAD -> origin/master origin/master root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git pull From https://gitee.com/hrKiley/remove-gitcode*[new branch] dev -> origin/dev Already up to date. root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch -r origin/HEAD -> origin/master origin/dev origin/master
*master 为本地 master 分支 origin/master origin/dev 为远程 master/dev 分支
git branch :查看的是本地分支
git branch -r:查看的远程分支
另一个用户在 windows 环境下任意位置,再 clone 同⼀个项⽬仓库

clone 成功

到此为止,准备工作已经完成,整体结构如图所示:

准备工作已经完成,现在实现多人协作一,任务如下:

在本地创建 dev 分支,再与远程 dev 分支进行连接:
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git checkout -b dev origin/dev branch 'dev'set up to track 'origin/dev'. Switched to a new branch 'dev'
git checkout -b dev的作用是创建本地 dev 分支并切换到此分支
origin/dev为连接远程 dev 分支,这样子就不需要 加上 <远程主机名> <本地分⽀名>:<远程分⽀名>
注意:
所有修改必须在本地分支下进行后再 push 到远程分支,不可以且不支持直接在远程分支上修改
git branch -vv命令可以看到分支建立连接情况
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch -vv* dev e4931b9 [origin/dev] update file.txt. master e69a904 [origin/master: ahead 1] 测试忽略特殊文件
对 file.txt 文件进行修改,并提交 push 到远程仓库
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# vim file.txt root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat file.txt create file pull aaa root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git status On branch dev Your branch is up to date with 'origin/dev'. Changes not staged for commit: (use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory) modified: file.txt Untracked files: (use "git add <file>..." to include in what will be committed) i.ini no changes added to commit (use "git add" and/or "git commit -a") root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git add file.txt root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git commit -m "md file:aaa"[dev dcad356] md file:aaa 1 file changed, 2 insertions(+), 1 deletion(-) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git push Username for'https://gitee.com': hrKiley Password for'https://[email protected]': Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Delta compression using up to 2 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 270 bytes | 270.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag 59434582 To https://gitee.com/hrKiley/remove-gitcode.git e4931b9..dcad356 dev -> dev
push 成功,我们再码云查看后,可以看到修改内容

开发者 2 的操作和开发者 1 一样,只不过是新增加的是'bbb'。
在本地创建 dev 分支,再与远程 dev 分支进行连接,对 file.txt 文件进行修改,并提交 push 到远程仓库
PS D:\code\tests\remove-gitcode> git checkout -b dev origin/dev Switched to a new branch 'dev' Branch 'dev'set up to track remote branch 'dev'from'origin'.PS D:\code\tests\remove-gitcode> git branch -vv * dev e4931b9 [origin/dev] update file.txt. master e4931b9 [origin/master] update file.txt.

PS D:\code\tests\remove-gitcode> cat.\file.txt create file pull bbb PS D:\code\tests\remove-gitcode> git add .\file.txt PS D:\code\tests\remove-gitcode> git commit -m "md file:bbb"[dev 711c72e] md file:bbb 1 file changed, 2 insertions(+), 1 deletion(-)PS D:\code\tests\remove-gitcode> git push info: detecting host provider for'https://gitee.com/'... info: detecting host provider for'https://gitee.com/'... info: detecting host provider for'https://gitee.com/'... To https://gitee.com/hrKiley/remove-gitcode.git ![rejected] dev -> dev (fetch first) error: failed to push some refs to 'https://gitee.com/hrKiley/remove-gitcode.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g.,'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help'for details.
提示了错误未能推送,远程仓库包含您本地没有的工作。推送失败复合预期,两次推送都是争对 file 文件,有本地提交和远程提交,两次提交发生冲突,修改的是同一行,Git 无法确定是要保留'aaa'还是换成'bbb'呢,所有只能手动解决。
Git 也给我们提供的解决方案,先将远程 pull 到本地后进行冲突解决再 push 到远程。
hint: (e.g.,'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help'for details.
执行 pull,查看冲突
PS D:\code\tests\remove-gitcode> git pull remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (3/3), 250 bytes | 62.00 KiB/s, done.From https://gitee.com/hrKiley/remove-gitcode e4931b9..dcad356 dev -> origin/dev Auto-merging file.txt CONFLICT (content): Merge conflict in file.txt Automatic merge failed; fix conflicts and then commit the result.
提示了'CONFLICT (content): Merge conflict in file.txt'冲突内容在 file 文件中,我们打开 file 文件查看

非常熟悉的画面,aaa 和 bbb 冲突了,之前已经学过如何解决冲突了,就是将内容改成我们想要的结果后 add 和 commit 后再 push 提交就可以了

PS D:\code\tests\remove-gitcode> cat.\file.txt create file pull bbb aaa PS D:\code\tests\remove-gitcode> git status On branch dev Your branch and 'origin/dev' have diverged, and have 1 and 1 different commits each, respectively.(use "git pull" to merge the remote branch into yours) You have unmerged paths.(fix conflicts and run "git commit")(use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: file.txt no changes added to commit (use "git add" and/or "git commit -a")PS D:\code\tests\remove-gitcode> git add .\file.txt PS D:\code\tests\remove-gitcode> git commit -m "merge dev"[dev e95ebf8] merge dev PS D:\code\tests\remove-gitcode> git push info: detecting host provider for'https://gitee.com/'... info: detecting host provider for'https://gitee.com/'... info: detecting host provider for'https://gitee.com/'... warning: auto-detection of host provider took too long (>2000ms) warning: see https://aka.ms/gcmcore-autodetect for more information. Enumerating objects: 10, done. Counting objects: 100% (10/10), done. Delta compression using up to 16 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 536 bytes | 536.00 KiB/s, done. Total 6 (delta 2), reused 0 (delta 0), pack-reused 0 remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag a14c5691 To https://gitee.com/hrKiley/remove-gitcode.git dcad356..e95ebf8 dev -> dev
这样子 push 成功了,查看码云效果也是如此

开发者们在 dev 分支做的差不多了最后一步就是将开发后的 dev 分支代码合并到 master 上,因为两个开发者的操作一样,这边以开发者 1 为例
分为两个方式:
通过 PR(Pull Request),远程仓库的方法(这个方式在多人协作二中具体演示)

RP 方式是需要审查员的审核的
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch * dev master root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git pull remote: Enumerating objects: 10, done. remote: Counting objects: 100% (10/10), done. remote: Compressing objects: 100% (4/4), done. remote: Total 6 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (6/6), 516 bytes | 516.00 KiB/s, done.From https://gitee.com/hrKiley/remove-gitcode dcad356..e95ebf8 dev -> origin/dev Updating dcad356..e95ebf8 Fast-forward file.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat file.txt create file pull bbb aaa
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit.(use "git push" to publish your local commits) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch dev * master root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git pull Already up to date.
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git checkout dev Switched to branch 'dev' Your branch is up to date with 'origin/dev'. root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch * dev master root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git merge master Already up to date.
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit.(use "git push" to publish your local commits) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git branch dev * master root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git merge dev Updating e69a904..84a529b Fast-forward file.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat file.txt create file pull bbb aaa
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git push Username for'https://gitee.com': hrKiley Password for'https://[email protected]': Enumerating objects: 8, done. Counting objects: 100% (8/8), done. Delta compression using up to 2 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 614 bytes | 614.00 KiB/s, done. Total 6 (delta 2), reused 0 (delta 0), pack-reused 0 remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag d444c094 To https://gitee.com/hrKiley/remove-gitcode.git e4931b9..84a529b master -> master

直接在码云删除 dev 分支:

多人在一个分支开发必然会带来冲突,所以在大多数情况下是不会采取 '多人协作一' 的那种方式
⼀般情况下,如果有多需求需要多⼈同时进⾏开发,会是⼀个需求或⼀个功能点就要创建⼀个 feature 分⽀。
现在实现多人协作二,任务如下:

在 '多人协作一' 我们是通过在远程创造分支,再 pull 到本地分支进行连接,这次我们换一种方式,不在远程创造分支,而是在本地完成后 push 到远程
不建议本地创建后 push,因为远程得 master 永远是最新的,本地的 master 不一定是最新的,这次多人协作二仅仅为了展示与多人协作一的不同方式
在本地创建 feature-1 分支并切换此分支,创建 function1 文件后,add 和 commit
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git checkout -b feature-1 Switched to a new branch 'feature-1' root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# vim function1 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# cat function1 i am coding... Done! root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git add function1 root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git commit -m "add func1"[feature-1 cf5b1f6] add func1 1 file changed, 2 insertions(+) create mode 100644 function1
由于我们并没有将 feature-1 进行连接,不能直接 push,所以我们得使用git push origin feature-1强行推送
root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git push #推送失败 fatal: The current branch feature-1 has no upstream branch. To push the current branch and set the remote as upstream, use git push --set-upstream origin feature-1 To have this happen automatically for branches without a tracking upstream, see 'push.autoSetupRemote' in 'git help config'. root@iZbp16khlytibqc83gbmonZ:~/remove-gitcode# git push origin feature-1 Username for'https://gitee.com': hrKiley Password for'https://[email protected]': Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 2 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 281 bytes | 281.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag 4a48b7a1 remote: Create a pull request for'feature-1' on Gitee by visiting: remote: https://gitee.com/hrKiley/remove-gitcode/pull/new/hrKiley:feature-1...hrKiley:master To https://gitee.com/hrKiley/remove-gitcode.git *[new branch] feature-1 -> feature-1
[* [new branch] feature-1 -> feature-1]
可以看到 Git 为我们新建了一个 feature-1 远程分支
使用 git branch -a 查看一下,远程出现了 feature-1 分支
远端码云可以查看到出现了新分支 feature-1,有 function1 文件且内容也出来了:

开发者 2 和开发者 1 操作的步骤是一样的。
为了保障是最新的 master,我们也需要 pull 一下远程仓库的 master
PS D:\code\tests\remove-gitcode> git checkout master Switched to branch 'master'PS D:\code\tests\remove-gitcode> git pull Updating e4931b9..84a529b Fast-forward .gitignore | 4 ++++ file.txt | 4 +++- s.so | 0 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 s.so
在本地创建 feature-2 分支并切换此分支,创建 function2 文件后,add 和 commit
PS D:\code\tests\remove-gitcode> git checkout -b feature-2 Switched to a new branch 'feature-2'

PS D:\code\tests\remove-gitcode> cat.\function2.txt i am coding...PS D:\code\tests\remove-gitcode> git add .\function2.txt PS D:\code\tests\remove-gitcode> git commit -m "add func2"[feature-2 1e90852] add func2 1 file changed, 1 insertion(+) create mode 100644 function2.txt
和开发者遇到的情况一样,不能直接 push,所以还是使用git push origin feature-2强行推送
PS D:\code\tests\remove-gitcode> git commit -m "add func2"[feature-2 1e90852] add func2 1 file changed, 1 insertion(+) create mode 100644 function2.txt PS D:\code\tests\remove-gitcode> git push origin feature-2 info: detecting host provider for'https://gitee.com/'... info: detecting host provider for'https://gitee.com/'... info: detecting host provider for'https://gitee.com/'... Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 16 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 278 bytes | 278.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 remote: Powered by GITEE.COM [1.1.23] remote: Set trace flag e34fdc8b remote: Create a pull request for'feature-2' on Gitee by visiting: remote: https://gitee.com/hrKiley/remove-gitcode/pull/new/hrKiley:feature-2...hrKiley:master To https://gitee.com/hrKiley/remove-gitcode.git *[new branch] feature-2 -> feature-2
[* [new branch] feature-2 -> feature-2]
也可以看到 Git 为我们新建了一个 feature-2 远程分支
查看码云,现在一共有三个分支:

各自的分支八竿子打不着所以两个开发者 push 并没有遇到冲突,此时各个仓库的状态如下:

依然是两个方式:
可自定义标题,再将具体内容填写


点击创建 Pull Request按钮后,Pull Request 后面出现数字,点击数字,进入此页面,此页面不再是开发人员的操作的内容了,而是审查人员和测试人员。
这边演示将 feature-2 合并到 master 中,选择源分支选框中的 function2

打开 Pull Request 页面点击新建 Pull Request



作为审查人员,我们可以看到源分支和目标分支的差异,如果觉得没问题可以点击已阅,再进行代码评审后提交就代表审查完成

审查完成后,点击'合并分支'后点击接受 Pull Request则合并完成

因为和多人协作一操作过整体思想是一样的,如下图所示,不再做演示


微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 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