文章目录
- 一、Git相关概念
- 二、本地分支中文件的添加 、提交
- 2.1 文件状态
- 2.2 创建Git仓库
- 2.2.1 git init
- 2.2.2 git clone
- 2.3 添加操作(git add)
- 2.4 提交操作(git commit)
- 2.5 撤销操作
- 2.5.1 撤销 add操作
- 2.5.2 撤销 commit操作
- 2.5.3 覆盖上一次的commit操作
- 2.6 远程仓库操作
- 2.7 查看提交历史
- 2.8 查看文件状态
- 2.8.1 git status
- 2.8.2 git diff
- 三、Git分支管理
- 3.1 git分支的分类
- 3.2 查看分支信息
- 3.3 新建分支
- 3.3.1 新建本地分支
- 3.3.2 新建远程分支
- 3.4 删除分支
- 3.4.1 删除本地分支
- 3.4.2 删除远程分支
- 3.4.3 删除远程追踪分支
- 3.5 分支重命名
- 3.5.1 本地分支重命名
- 3.5.2 远程分支重命名
- 3.6 关联本地分支与远程追踪分支
- 3.7 切换分支(git checkout)
- 3.8 拉取更新(git fetch)
- 3.9 合并分支(git merge)
- 3.9.1 git merge讲解
- 3.9.2 撤销合并
- 3.10 变基操作(git rebase)
- 基本用法:
- 进阶用法:
- 3.11 拉取操作(git pull)
- 3.12 推送操作(git push)
- 3.13 合并冲突的解决
- 四、标签操作(git tag)
- 4.1 创建标签
- 4.2 查看标签
- 4.3 删除标签
- 4.4 推送标签到远程仓库
- 4.5 检出标签(创建分支)
- 五、暂存操作(git stash)
- 六、本地仓库的更新以及冲突解决
- 6.1 直接克隆项目远程仓库
- 6.2 Fork项目远程仓库
一、Git相关概念
git 在线演示网站:git 在线演示
讲解Git工作流程之前,先讲下Git仓库相关概念:
工作区(Workspace)
:自己存放代码的文件夹(除.git外)暂存区(Index)
:.git
文件夹下的index文件本地仓库(Local Repository)
:.git
文件夹远程仓库(Remote Repository)
:在远程服务器上的Git仓库,存放代码
二、本地分支中文件的添加 、提交
2.1 文件状态
未跟踪(Untracked)
:这是文件的初始状态,表示该文件尚未被Git跟踪。当你在项目目录中创建一个新文件时,它将处于未跟踪状态。已修改(Modified)
:表示已经跟踪的文件发生了更改,但这些更改还没有被提交到本地仓库。已暂存(Staged)
:表示已跟踪文件中的更改已经添加到Git的暂存区(Stage/Index),但是没提交到本地仓库。已提交(Committed)
:表示文件的更改已经被提交到了本地仓库中。
2.2 创建Git仓库
有两种取得 Git 项目仓库的方法:
- 在现有项目或目录下导入所有文件到 Git 中;
- 从一个服务器克隆一个现有的 Git 仓库。
2.2.1 git init
- 初始化指定目录作为Git本地仓库
git init [dir_name]
1. 假如只执行 git init ,那么就是初始化当前目录作为Git仓库
2. 假如 dir_name 不存在,会当前目录中创建一个 dir_name 文件夹,文件夹中含有一个 .git文件夹
3. dir_name存在,dir_name文件夹会多出一个 .git文件夹
- 连接Git远程仓库
git remote add [shortname] [url]
1. shortname: 远程仓库别名
2. url: 远程仓库地址
git remote [-v] //显示所有远程仓库的名称
-v 还可以查看到远程仓库的地址,以及每个远程仓库的读取(fetch)和写入(push)权限
# 移除远程仓库与本地仓库的关系
git remote rm [shortname]
2.2.2 git clone
当你执行 git clone <remote>
命令时,Git 会克隆整个远程仓库到本地(包括了远程仓库中的所有分支
、标签以及所有提交的历史记录),本地会生成本地主分支
和远程追踪分支
。
本地仓库的
远程追踪分支
在后面的《git分支的分类》小节中有解释
git clone [option] <repository_url> [<directory>]
-
<repository_url>
: 远程仓库的地址。 -
<directory>
: 存放远程仓库代码的目录,假如该目录不存在,会在当前目录下创建同名子目录 -
[option]
: 可用选项。以下是一些常用的git clone
选项:-
--depth <depth>
:指定克隆的深度,即历史提交记录的数量。使用深度克隆可以减少克隆所需的时间和下载的数据量。--depth 1
代表只克隆最近一次的提交内容。 -
-b <branch>
或--branch <branch>
:本地仓库生成<branch>
分支,远程追踪分支跟踪远程仓库的所有分支。如果不指定分支,本地生成主分支,远程追踪分支跟踪远程仓库的所有分支。
-
--single-branch
或--no-single-branch
:本地仓库生成一个主分支,远程追踪分支只跟踪远程仓库的主分支。可以结合-b <branch>
选项来指定克隆的分支:本地仓库生成一个<branch>
分支,远程追踪分支跟踪远程仓库的<branch>
分支。
上面这些图中的红色字体,就是远程追踪分支。
-
--shallow-since <date>
:指定自特定日期以来的历史提交记录数量,进行浅层克隆。 -
--jobs <n>
:指定克隆过程中使用的并发作业数量,加快克隆速度。 -
--origin <name>
:设置克隆存储库的远程名称。默认情况下,使用 “origin” 作为远程名称。
-
2.3 添加操作(git add)
git add [file1] [file2] ...
- 添加指定文件到暂存区
[file]
是文件的路径,根目录是工作目录。
git add [dir]
- 添加指定目录到暂存区,包括子文件夹
git add .
- 将当前目录中的所有改动的文件添加到暂存区
2.4 提交操作(git commit)
要将暂存区中的文件提交到本地仓库,你可以使用 git commit
命令。这个命令会创建一个新的提交,并将暂存区中的文件作为该提交的内容。
-
git commit -m "commit message"
- -m 选项用于指定提交的消息(commit message),后面跟着双引号括起来的消息内容。
-
git commit [file1] [file2]...-m "commit message"
- 提交指定文件
-
git commit -v
- 提交时显示所有的diff信息
-
git commit -amend -m "commit message"
-
将此次的提交替代最近一次的提交。此次提交会完成两个动作:①提交暂存区中的更改,②指定提交信息。
-
如果在替代上一次提交的基础上,提交新的更改,那么执行如下步骤
git add <new_file>
git commit --amend -m "New commit message"
-
git commit -am "commit message"
-a
选项:自动将所有未跟踪的文件添加到暂存区,省去了git add
步骤-m
选项:指定提交的信息(commit message),后面跟着双引号括起来的消息内容
在提交之前,确保你已经通过
git add
命令将要提交的文件添加到暂存区中。如果还有未添加到暂存区的修改或新增文件,可以使用git add
命令将它们添加到暂存区,然后再执行git commit
进行提交。
2.5 撤销操作
2.5.1 撤销 add操作
有以下几种方式可以撤销git add
操作但更改仍保留在工作区的修改:
git rm --cache [file]
git reset HEAD [file]
:这个命令将指定的文件从暂存区中移除,但保留在工作区的修改。它实际上是将文件的状态重置为上一次提交时的状态,相当于取消对文件的暂存。git restore --staged [file]
:这个命令将指定的文件从暂存区中移除,并恢复到工作区中最近一次提交的版本,保留工作区的修改。git rm --cached [file]
:这个命令与git rm --cache [file]
是等效的,用于从暂存区中移除文件而保留工作区的修改。
执行
git add
命令时,不小心将某个不添加到暂存区中的文件提交到了暂存区,如何解决呢?
git rm --cached <file>
、git reset <file>
将指定文件从暂存区中删除,不会影响工作区中的文件。
2.5.2 撤销 commit操作
撤销操作需要用到 命令:git reset
。
-
git reset --soft <commit>
:只影响本地仓库的当前分支- 用于将当前分支的 HEAD 指针回退到指定的
<commit>
。 git reset --soft HEAD^
让当前分支的HEAD指针回退到上一次提价的位置
- 用于将当前分支的 HEAD 指针回退到指定的
-
git reset [--mixed] <commit>
:撤销add 、commit操作,但是不覆盖工作区中的改动- 将当前分支的 HEAD 指针移动到指定的
<commit>
,同时重置暂存区,将之后的修改放入工作目录中。
- 将当前分支的 HEAD 指针移动到指定的
-
git reset --hard <commit>
:撤销add 、commit操作,同时覆盖工作区中的改动- 将当前分支的 HEAD 指针移动到指定的
<commit>
,同时重置暂存区和工作目录,和<commit>
保持一致
- 将当前分支的 HEAD 指针移动到指定的
-
git checkout --file
:撤销对file文件的修改,丢弃当前未暂存或者已暂存的该文件的更改。
<commit>
是一个表示提交的标识符,可以是commit的哈希值、分支名或者其他引用。
- 哈希值:通过
git log
命令查看提交历史并找到你想要回滚的commit哈希值。- 分支名:
git reset --soft main
来将当前分支重置到main
分支所指向的 commit。这样做将会将当前分支的 HEAD 移动到main
分支所在的位置。HEAD
表示:
- 你当前所在的工作目录中正在工作的分支的最新提交。
- 还指向分支名的引用。当你切换分支时,
HEAD
会跟随并指向新的分支名,从而指示你正在工作的是哪个分支。例如,当你处于main
分支上时,HEAD
指向main
分支最新的提交。HEAD^
表示HEAD
所指向的提交的上一次提交,HEAD^^
表示HEAD^
所指向的提交的上一次提交;HEAD~1
等价与HEAD^
,HEAD~2
等价与HEAD^^
。
2.5.3 覆盖上一次的commit操作
# 使用一次新的commit来替代上一次提交,如果代码没有变化,则改写提交信息
git commit -amend -m "commit message"
2.6 远程仓库操作
git remote -v
- 显示所有远程仓库的信息
git remote show [remote]
- 显示某个远程仓库的信息
git remote add [shortname] [url]
- 添加一个远程仓库并命名
git remote rm [shortname]
- 删除远程仓库
git remote rename old_name new_name
- 对远程仓库重命名
git remote set-url [shortname] url
- 修改已经存在的远程仓库的
URL
shortname
: 远程仓库在本地的名称url
: 远程仓库的url
- 修改已经存在的远程仓库的
2.7 查看提交历史
git log
用于查看当前分支的提交历史记录。通过执行 git log
命令,你可以看到每个提交的详细信息,例如提交作者、提交日期、提交消息和提交哈希值等。
git log
命令会按时间顺序列出提交历史,最新的提交会显示在最上面。你可以通过按 Enter
键向下滚动查看更多提交历史,如果想退出查看历史,可以按 Q
键。
2.8 查看文件状态
2.8.1 git status
git status
是 Git 中一个极其重要的命令,它用于展示当前工作目录和暂存区(Index)的文件状态以及与仓库中最新提交版本的差异。当你执行 git status
时,Git会输出以下关键信息:
-
当前分支:
显示你所在的工作分支名称。 -
与远程分支的关系:
如果本地分支与远程分支关联,并且已经获取了远程分支的最新更新,git status
可能会显示当前分支是否与远程分支同步或落后/超前多少个提交。 -
未暂存的修改(Changes not staged for commit):
列出所有已修改但尚未添加到暂存区(通过git add
命令)的文件。这些改动在下次提交之前不会被包含进去。 -
新增的未追踪文件(Untracked files):
显示那些新创建的、尚未被 Git 版本控制跟踪的文件。若要将它们纳入版本控制,首先需要使用git add
将它们加入暂存区。 -
已暂存的更改(Changes to be committed):
如果有文件已被git add
添加到了暂存区,则会显示这部分即将被提交的更改。
一个典型的 git status
输出可能如下所示:
On branch develop
Your branch is up to date with 'origin/develop'.
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: src/app.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
new_file.txt
no changes added to commit (use "git add" and/or "git commit -m '...'" to commit your changes)
git status -s
或 git status --short
是 Git 中 status
命令的简洁输出模式。它以更紧凑的形式展示当前工作目录和暂存区的状态,便于快速查看。
在 -s
短格式输出中,Git 会按照以下规则显示文件状态:
??
- 未跟踪的新文件,即新创建的文件但没有执行
git add
命令。
- 未跟踪的新文件,即新创建的文件但没有执行
M
- 表示文件已修改,但是这些改动还没有被添加到暂存区。
MM
- 表示文件已修改,暂存后又作了修改,因此该文件的修改中既有已暂存的部分,也有未暂存的部分。
A
- 表示该文件是新添加到暂存区(Index)的文件,即通过
git add
命令将一个新创建或从未被 Git 跟踪过的文件放入了暂存区。这个文件将在下一次提交时成为仓库的一部分。
- 表示该文件是新添加到暂存区(Index)的文件,即通过
2.8.2 git diff
git diff
是 Git 中的一个核心命令,用于比较文件或目录的不同版本之间的差异。这个命令在开发过程中极其有用,可以帮助你查看尚未提交的更改、暂存区与工作目录之间、两个分支之间的内容区别等。
以下是 git diff
的几个典型用法及详细解释:
-
查看未暂存的改动:
git diff
此命令显示当前工作目录中已修改但还未添加到暂存区(Index)的文件内容差异。每一行显示了具体的增删改行,并以特殊字符标识出增加 (
+
)、删除 (-
) 或移动的内容。 -
查看暂存区与上次提交的差异:
git diff --cached [file]
或者
git diff --staged [file]
这将展示已暂存但未提交的改动。如果不指定文件名,则会显示所有已暂存文件的差异。
-
比较工作目录和任意提交之间的差异:
git diff HEAD [file]
或者对比两个commit之间的差异:
git diff <commit1>..<commit2>
这里
<commit1>
和<commit2>
可以是任何提交哈希值、分支名或标签。此命令会展示从<commit1>
到<commit2>
之间的所有文件差异。 -
比较两个文件或目录:
git diff <file1> <file2>
或者
git diff <directory1> <directory2>
当比较的是两个具体路径时,Git会逐个文件进行比较并显示它们之间的差异。
-
格式化输出差异:
git diff --word-diff
或者使用其他格式选项来增强可读性,如高亮差异单词而非整行、创建统一或彩色输出等。
-
输出为补丁文件:
git diff > changes.patch
将差异信息输出到一个名为
changes.patch
的文件中,这样可以方便地保存、发送或应用这些更改。 -
合并请求或拉取请求中的diff预览:
在GitHub或其他Git托管平台中,你可以直接查看pull request或者merge request中的git diff
输出,它展示了即将合并进目标分支的所有更改。
三、Git分支管理
3.1 git分支的分类
git分支分为本地分支
、远程追踪分支
和远程分支
之分。
本地分支
、远程追踪分支
和远程分支
是 Git 中三种不同类型的分支,它们在用途和作用上有一些区别:
本地分支(Local Branch)
:- 本地分支是在本地仓库中创建的分支,用于在开发过程中进行不同功能或版本的并行开发。
- 你可以在本地分支上进行代码的修改、提交、合并等操作,是开发过程中实际工作的分支。
- 本地分支的命名通常不包含远程仓库的名称前缀,直接使用分支名即可。
远程追踪分支(Remote Tracking Branch)
:- “远程追踪分支”(Remote Tracking Branch)是指与远程仓库中的分支相关联的本地分支,用于跟踪远程仓库的分支状态。当你与远程仓库建立关联(例如通过
git clone
克隆远程仓库时),本地仓库会自动创建对应的远程追踪分支。远程追踪分支的命名通常为<remote-name>/<branch-name>
,其中<remote-name>
是远程仓库的名称,<branch-name>
是远程仓库中的分支名。 - 它是对远程仓库分支的镜像,记录了远程仓库分最新状态,而不需要直接访问远程仓库。
- 远程追踪分支还指示了远程仓库的位置和分支信息,方便你在多个远程仓库之间进行切换和操作。
- 远程追踪分支的命名通常为
<remote-name>/<branch-name>
,其中<remote-name>
是远程仓库的名称,<branch-name>
是远程仓库中的分支名。 git fetch
或git pull
命令将远程仓库的更新下载到本地,并更新对应的远程追踪分支。这样你可以在本地查看远程仓库的最新状态,决定是否需要进行合并或推送操作。但它不能直接在本地进行修改和提交,只能通过同步远程仓库来更新。- 远程追踪分支与本地分支之间可以进行合并操作。当你在本地分支上执行
git merge
或git pull
命令,并指定远程追踪分支作为合并来源,Git 将会将远程分支的更改合并到当前本地分支上。这样可以将远程仓库的更新合并到你正在工作的本地分支中。
- “远程追踪分支”(Remote Tracking Branch)是指与远程仓库中的分支相关联的本地分支,用于跟踪远程仓库的分支状态。当你与远程仓库建立关联(例如通过
远程分支(Remote Branch)
:- 远程分支是存储在远程仓库中的分支,通常是由其他开发者推送到远程仓库的。
- 远程分支对于本地仓库而言,是不可编辑的,你无法在本地直接修改或提交远程分支。
- 远程分支的命名同样使用
<remote-name>/<branch-name>
的形式,其中<remote-name>
是远程仓库的名称,<branch-name>
是远程仓库中的分支名。 - 当你克隆远程仓库或者进行远程仓库更新时,会自动为本地仓库创建相应的远程追踪分支,用于跟踪远程分支的状态。
区别总结:
- 本地分支是在本地仓库中创建的用于开发的分支,可以在本地进行修改和提交操作。
- 远程追踪分支是本地仓库中的引用,用于跟踪远程仓库分支状态,只能通过
git fetch
或git pull
同步远程仓库。 - 远程分支是存储在远程仓库中的分支,不能在本地直接编辑和提交,只能通过远程仓库的更新来同步。本地仓库会自动为远程分支创建对应的远程追踪分支。
<remote>/<branch>
既可以表示远程仓库中的远程分支,也可以表示本地的远程追踪分支
3.2 查看分支信息
git branch
- 查看本地仓库中的分支
git branch -r
- 查看所有远程仓库中的所有分支
git branch -a
- 查看所有分支信息,包括本地分支和远程追踪分支
git branch -vv
- 查看本地分支和远程分支的关联情况
以上所有命令显示的结果中,
*
会标注在当前分支的前面。
git branch -a
显示的远程追踪分支会用红色字体标注。
git branch -vv
显示的内容中最后一列是最近一次提交commit的注释。
3.3 新建分支
3.3.1 新建本地分支
git branch <new_local_branch>
- 新建本地分支,但不会切换到新建分支下,依然处于当前分支;
git checkout -b <new_local_branch>
、git switch -c <new_local_branch>
- 新建本地分支,但是并切换到新建分支下;
git checkout -b <new_local_branch> <remote>/<remote_branch>
- 新建本地分支,并切换到新建分支下,同时和远程分支建立联系
- 如果本地仓库关联了一个远程仓库,那么可以省略
<remote>
,即:git checkout -b <new_local_branch> <remote_branch>
git branch
显示的当前分支为master
,那么git branch test
命令新建的分支test
是基于master
分支新建的,并且该分支仅存在本地中。
3.3.2 新建远程分支
新建远程分支的本质是新建本地分支,然后将本地分支推送到远程仓库。远程仓库中没有与本地仓库新建的分支同名的分支,那么git会新建一个同名的远程分支。
git push -u <remote> <remote-branch>:<local-branch>
- <remote-branch>: 远程仓库的分支, 假如远程分支不存在, 会创建一个远程分支
git push -u <remote> <local_branch>
- <remote>: 远程仓库;
- <local_branch>: 本地分支,假如远程仓库没有<local_branch>, 那么会在远程仓库中创建一个远程分支。
3.4 删除分支
3.4.1 删除本地分支
git branch -d <local_branch>
git branch -D <local_branch>
- 假如你当前处于
dev
分支,那么执行git branch -d dev
会失败。- -d表示安全删除已完成合并的分支,-D表示强制删除未完成合并的分支,包括还有未提交更改的分支。(这里的
合并
是本地分支的合并)
3.4.2 删除远程分支
git push origin --delete feature-branch
- origin: 远程仓库名
- feature-branch: 要删除的远程分支
- 该操作无法撤销
3.4.3 删除远程追踪分支
# 删除本地的远程追踪分支(remote tracking branch),不是删除远程仓库中的远程分支
git branch -d -r <remote>/<remote-branch>
-d: 删除分支
-r: 本地仓库中的远程追踪分支
- <remote>/<remote-branch>: 此处表示的是远程追踪分支
3.5 分支重命名
3.5.1 本地分支重命名
在Git中,修改分支名可以通过以下步骤完成:
假设你要将分支名从old-branch
修改为new-branch
:
-
确保你当前不在要修改的分支上:在执行修改分支名之前,先确保你当前不在
old-branch
分支上。可以切换到其他分支,例如主分支master
。git checkout master
-
重命名分支:使用
git branch -m
命令来修改分支名。git branch -m old-branch new-branch
这将把名为
old-branch
的分支重命名为new-branch
。 -
推送新的分支名到远程仓库(如果需要):如果你之前已经将
old-branch
推送到远程仓库,现在需要推送新的分支名new-branch
。git push origin new-branch
这将把修改后的
new-branch
分支推送到名为origin
的远程仓库。 -
删除旧分支(可选):如果你希望删除旧的分支名
old-branch
,可以使用以下命令:git branch -d old-branch
注意:使用
-d
参数是安全的删除方式,它会检查分支是否已经合并,如果没有合并,将会拒绝删除。如果想要强制删除未合并的分支,可以使用-D
参数:git branch -D old-branch
请注意,在修改分支名后,如果其他开发人员已经在远程仓库中拉取旧分支名的分支,他们需要更新本地仓库的分支名称。最好提前与团队进行沟通,以避免潜在的混淆和问题。
3.5.2 远程分支重命名
在 Git 中,修改远程分支名需要完成以下几个步骤:
-
确保本地仓库和远程仓库相关联:在执行下面的步骤之前,首先你需要将本地仓库与远程仓库关联起来。通常,你会在克隆(
git clone
)远程仓库到本地时自动完成这个步骤。如果没有关联,可以使用git remote add
命令添加远程仓库的地址。 -
修改本地分支名为
new-branch
:在本地仓库中使用以下命令将远程分支old-branch
修改为new-branch
:git branch -m old-branch new-branch
-
删除远程仓库的远程分支
old-branch
git push --delete <remote> <old-branch> - <remote> : 远程仓库 - <old-branch>: 远程仓库中的远程分支
-
将修改后的本地分支推送到远程仓库:
git push <remote> <new-branch> - <remote>:远程仓库 - <nnew-branch>: 远程分支
这将把本地仓库中的
new-branch
分支推送到远程仓库。
注意事项:
- 在修改远程分支名前,请确保你与团队中的其他成员进行充分沟通,以避免潜在的冲突和问题。
- 如果其他开发人员已经在远程仓库中拉取旧分支名的分支,他们需要更新本地仓库的分支名称。可以提醒他们执行
git fetch --all
更新远程分支列表。
请谨慎进行远程分支的重命名操作,确保你已经充分了解操作的影响,并在必要时备份重要的分支或提交。
3.6 关联本地分支与远程追踪分支
# 显示本地仓库中的所有分支与远程追踪分支的关联关系
git branch -vv
# 将本地分支<local-branch>和远程仓库<remote>的远程分支<remote-branch>建立联系, 当本地仓库只连接了一个远程仓库的时候,可省略 "<remote>/"
git branch --set-upstream-to=<remote>/<remote-branch> <local-branch>
git branch --set-upstream-to=<remote-branch> <local-branch>
git branch -u <remote>/<remote-branch> <local-branch> (较新版本的git中才能使用)
# 创建并切换到本地分支 new-local-branch , 关联远程仓库<remote>中的远程分支<remote-branch>
git checkout -b new-local-branch <remote>/<remote-branch>
# 将本地分支<branch>的更新推送到远程仓库的远程分支<branch>的同时建立关联
git push -u <remote> <branch>
# 取消本地分支<local-branch>与远程仓库中的远程分支<local-branch>的联系,若取消当前分支与远程分支的关联,可省略分支名。
git branch --unset-upstream <local-branch>
git branch --unset-upstream
上述命令中的
<remote>/<remote-branch>
表示的是远程仓库的远程分支。
3.7 切换分支(git checkout)
git checkout <branch>
- 切换到另一分支 ,切换分支前必须确保分支存在
- 新版本git使用命令:
git switch <branch>
git checkout -b <new_branch>
- 新建分支并切换到该分支
3.8 拉取更新(git fetch)
git fetch
用于从远程仓库获取更新并将它们同步到本地仓库的远程追踪分支
,但不会自动合并到当前工作分支。
git fetch <remote>
:将远程仓库的所有分支的更新同步到相应的远程追踪分支。git fetch <remote> <branch>
:将远程仓库<remote>
中指定分支<branch>
的更新同步到相应的远程追踪分支。git fetch <remote> <remote-branch>:<local-branch>
:将远程仓库<remote>
中指定分支<branch>
的更新同步到本地分支<local-branch>
,同步到工作区。
git fetch
命令的常用选项有那些:
-
--all
:将所有远程仓库的所有分支的更新同步到相应的远程追踪分支。 -
--tags
:获取远程仓库的标签(tags)更新。 -
--verbose
:在获取更新时显示详细的进度信息。
在本地仓库的
main
分支下,能否执行该命令:git fetch origin dev:main
?
- 该命令的作用是从远程仓库 (
origin
) 获取dev
分支的内容,并将其拉取到本地的main
分支。- 这可能会导致
main
分支的历史线与远程的dev
分支不同步。- 要想达到此效果,应该执行:
git fetch origin main
然后执行git merge dev
。
3.9 合并分支(git merge)
3.9.1 git merge讲解
git merge
命令用于将一个分支的更改合并到另一个分支。它是将不同分支上的工作合并到一起的主要机制之一。通常,你会在切换到目标分支后使用 git merge
命令将其他分支的更改合并到当前分支。
-
git merge <branch>
-
将分支合并到当前分支,
<branch>
既可以是本地分支,也可以是远程追踪分支。 -
# 切换到本地分支main git checkout main # 将dev分支合并到main分支 git merge dev
-
-
git merge --no-ff
:强制合并; -
git merge --abort
:取消合并; -
git merge --continue
:解决冲突后的继续合并操作。当你在执行git merge
进行分支合并时,如果合并过程中出现冲突,Git 会暂停合并并通知你发生了冲突。你需要手动解决冲突,然后使用git add <conflicted_file>
标记冲突已解决。接着,你可以使用git merge --continue
来继续合并操作。
有两种常见的合并类型:
合并分支
:将一个分支的更改合并到另一个分支上,以保持两个分支的修改一致。在执行git merge
命令时,会生成一个新的合并提交,包含了合并的内容。例如:# 切换到目标分支 git checkout target-branch # 合并源分支的更改到目标分支 git merge source-branch
合并提交
:将一个或多个特定的提交应用到当前分支上,而不是合并整个分支的历史。这通常使用git cherry-pick
命令来完成。例如:# 切换到目标分支 git checkout target-branch # 合并单个commit到目标分支 git cherry-pick <commit-hash>
3.9.2 撤销合并
撤销分支的合并:在当前分支下,使用 git reset 进行撤销
git reset --soft <commit>
:git reset --hard <commit>
:
3.10 变基操作(git rebase)
git rebase
是 Git 中一个非常有用的命令,它用于将一个分支的提交移动到另一个分支的基础上重新应用。通过重新应用提交,你可以创建一个线性的提交历史,使得项目的历史更加整洁和可读。下面是 git rebase
的详细讲解:
基本用法:
-
在当前分支上执行 rebase:
git checkout <target_branch> git rebase <base_branch>
这个命令会将
<target_branch>
上的提交逐个应用到<base_branch>
上,从而在<base_branch>
的最新提交之后创建一系列新的提交。 -
处理冲突:
如果在 rebase 过程中遇到冲突,Git 会暂停 rebase 进程,并让你解决冲突。解决完冲突后,使用git rebase --continue
继续 rebase 进程,或者使用git rebase --abort
中止 rebase 进程。 -
终止 rebase:
git rebase --abort
如果在 rebase 过程中遇到了问题或者需要放弃 rebase,可以使用此命令终止 rebase 进程,并且回到 rebase 之前的状态。
-
继续 rebase:
git rebase --continue
解决完冲突后,使用此命令继续进行 rebase 进程。
进阶用法:
-
交互式 rebase:
git rebase -i <base_branch>
使用交互式 rebase 可以对提交进行重新排序、合并、编辑提交消息等操作,从而可以更加灵活地管理提交历史。
-
指定基准提交:
git rebase --onto <new_base> <old_base> <branch>
这个命令允许你在指定的
<old_base>
和<new_base>
之间重新定义<branch>
的基础提交,从而可以将提交移动到一个新的基础上。 -
跳过提交:
git rebase --skip
如果在 rebase 过程中某个提交已经不再需要,则可以使用此命令跳过该提交。
-
修改 rebase 的默认行为:
你可以通过配置 Git 来修改 rebase 的默认行为,比如使用git config --global pull.rebase true
来设置在git pull
时默认使用 rebase。
git rebase
是一个非常强大的命令,可以帮助你整理提交历史、解决冲突并创建一个更加整洁的项目历史。但需要注意的是,在公共分支上进行 rebase 可能会改写提交历史,因此需要谨慎使用,以免影响到其他团队成员。
3.11 拉取操作(git pull)
git pull
命令用于从远程仓库拉取最新的提交和分支信息,并将远程分支的更新合并到当前所在的本地分支。它实际上是 git fetch
和 git merge
两个命令的组合,用于快速将远程仓库的更新同步到本地分支。
- 在执行
git pull
之前,确保你的工作目录是干净的,没有未提交的更改,以避免潜在的冲突。- 如果你在拉取过程中遇到冲突,需要手动解决冲突,标记为已解决,然后继续合并过程。解决冲突的步骤在后面小节会详细讲解。
git pull <remote> <remote_branch>
<remote_name>
: 远程仓库的名称,通常是 “origin”。<branch_name>
: 要拉取的远程分支的名称。- 将远程仓库中的
<remote_branch>
分支合并到当前本地分支。
git pull --all
- 拉取所有分支的更改
git pull <remote> <tag>
- 拉取某个特定标签所指向的提交
git pull --force <remote> <branch>
- 覆盖本地未提交(commit)的更改并强制拉取最新的远程更改。
3.12 推送操作(git push)
git push
命令有多种用法,可以满足不同的推送需求。以下是一些常见的 git push
用法:
-
git push [-u] <remote> <local_branch>
- 将指定的本地分支的更改推送到指定的远程仓库
-u
: 将推送的分支与远程分支进行关联。
-
git push [-u] <remote> <local_branch>:<remote_branch>
-u
: 将推送的分支与远程分支进行关联。这样,你以后只需要使用 git push 命令即可进行推送,Git 会自动推送到与当前分支关联的远程分支。remote
: 远程分支local_branch
: 本地仓库的分支remote_branch
: 远程仓库中的分支
-
git push --all <remote>
- 将本地仓库中的所有分支推送到远程仓库
-
git push -f <remote> <local_branch>
- 将本地分支中更改强制推送到远程仓库中。
-
git push <remote> --delete <branch>
- 删除远程仓库
<remote>
上的指定分支<branch>
。
- 删除远程仓库
-
git push --tags <remote>
- 将当前分支上的所有标签推送到远程仓库
3.13 合并冲突的解决
在执行命令git pull
或git merge
时,两个分支(本地分支与本地分支之间、本地分支与远程追踪分支之间)的更改
- 处于文件的同一位置,此时就会发生合并冲突。
- 处于文件的不同位置上或者不同文件中,此时不会发生合并冲突。
解决冲突有如下步骤:
- 打开修改合并冲突文件;
- 执行命令
git add <conflict_file>
标记冲突解决,同时将该文件添加到暂存区; - 执行命令
git merge --continue
,输入并保存提交信息,继续执行合并。
以下图为例,执行命令git fetch origin
–>git merge origin/master
产生了冲突
git fetch origin
:将远程仓库中的更新同步到本地的远程追踪分支
git merge origin/master
:将远程分支的更改合并到本地的当前分支。
Auto-merging
:提示在a.txt
文件中发生自动合并
Merge conflict in a.txt
:提示在a.txt
文件中产生合并冲突。
- 解决冲突:
- 打开并修改
a.txt
文件,保留自己想要的更改。 - 执行命令
git add a.txt
,标记冲突已解决,同时将解决后的文件添加到暂存区。 - 执行命令
git merge --continue
,Git会打开一个文件,输入此次提交信息(合并本质是提交commit),然后按esc
键,输入:wq
保存该文件,然后Git保存后会提交该合并。
- 打开并修改
四、标签操作(git tag)
Git 的标签(tags)是用于标记特定提交的命名引用,通常用于标记版本发布。标签是不可变的,一旦创建就不能修改,这使得它们适合用于标识软件的发布版本。
4.1 创建标签
-
git tag <tag_name>
- 这个命令会在当前提交上创建一个轻量级标签。轻量级标签仅仅是一个指向特定提交的引用。
-
git tag -a <tag_name> -m "Tag message" <commit_hash>
- 创建一个带注解的标签,其中
-a
表示创建一个带注解的标签,-m
用于指定标签的描述信息,<commit_hash>
是要标记的特定提交的哈希值
附注标签和轻量级标签的区别:
- 附注标签包含标签本身的信息以及标签所指向的提交的哈希值。
- 轻量级标签只是一个不含附加信息的引用。
- 创建一个带注解的标签,其中
4.2 查看标签
git tag
- 查看所有标签
git show <tag_name>
- 显示指定标签的详细信息,包括标签的提交信息和提交内容的变化。
4.3 删除标签
git tag -d <tag_name>
- 删除指定的本地标签
4.4 推送标签到远程仓库
git push <remote> <tag_name>
- 推送指定标签到远程仓库中。
git push <remote> --tags
- 推送所有标签到远程仓库
4.5 检出标签(创建分支)
git checkout -b <branch_name> <tag_name>
- 在指定的标签位置创建一个新的分支
五、暂存操作(git stash)
git stash
是 Git 中一个非常实用的命令,它允许你在不提交代码的情况下临时存储当前工作目录和暂存区(Index)中的所有更改。当你需要切换分支、处理紧急问题或者清理工作环境而又不想丢失当前正在进行的工作时,这个命令就显得尤为重要。
-
git stash
、git stash save
、git stash save "message"
- 作用:保存暂存区和工作目录中所有已跟踪文件的更改,但是不保存未跟踪的文件(即那些尚未被
git add
添加到暂存区的新文件或不在版本控制下的文件)。而且存储到一个栈式的列表中。 git stash
和git stash save
作用一样。"message"
:stash
记录的自定义描述信息。
- 作用:保存暂存区和工作目录中所有已跟踪文件的更改,但是不保存未跟踪的文件(即那些尚未被
-
git stash -u
、git stash --include-untracked
- 将所有已跟踪(即已经被 Git 知道并加入版本控制的)且未暂存的更改存入stash,并且同时也会包含那些被 Git 记录但尚未添加到暂存区(即
.gitignore
文件中没有忽略掉的)的未追踪文件。也就是说,这个选项会储存那些Git已经知道存在但还没有正式追踪(通过git add
添加)的任何更改。
- 将所有已跟踪(即已经被 Git 知道并加入版本控制的)且未暂存的更改存入stash,并且同时也会包含那些被 Git 记录但尚未添加到暂存区(即
-
git stash -a
、git stash --all
- 不仅会存储所有已跟踪文件的未提交更改(无论是否已暂存),而且还会包括工作目录中的所有未追踪文件,无论这些文件之前是否曾经被Git跟踪过。这意味着即使对于全新创建、从未被
git add
过的文件,只要它们存在于工作目录下,都会被保存至stash中。
-u
只包括已被Git知晓但还未被追踪的未暂存文件。-a
包括所有未追踪文件,不管它们之前是否有过追踪记录。
- 不仅会存储所有已跟踪文件的未提交更改(无论是否已暂存),而且还会包括工作目录中的所有未追踪文件,无论这些文件之前是否曾经被Git跟踪过。这意味着即使对于全新创建、从未被
-
git stash list
- 列出所有已存储的
stash
及其简短描述和索引编号。
- 列出所有已存储的
-
git stash apply [stash@{index}]
git stash apply
:应用最近stash
的内容到当前工作目录,但不会从stash
列表中移除。git stash apply stash@{index}
:应用指定stash
的内容到当前工作目录,但不会从stash
列表中移除。
-
git stash pop [stash@{index}]
- 类似于
apply
,但它在应用后还会自动删除列表中之前应用的stash
记录。
- 类似于
-
git stash drop [stash@{index}]
git stash drop
:删除最近的stash
。git stash drop stash@{index}
:应用指定的stash
。
-
git stash clear
- 删除所有的
stash
- 删除所有的
六、本地仓库的更新以及冲突解决
当远程仓库的代码更新了之后,需要将代码更新到本地工作区中,如何操作呢?
6.1 直接克隆项目远程仓库
-
在gitee上创建了一个远程仓库
AA
(远程仓库中只有一个空文件a.txt
)。在本地的两个文件夹A
、B
中分别克隆了远程仓库AA(A、B文件夹相当于两个人的工作文件夹,A、B文件夹下的克隆操作相当于两个用户都克隆了项目代码) -
在A文件夹中,对文件中的代码进行修改,然后提交并推送更改到远程仓库
- 在B文件夹中,对文件中的代码进行修改,然后提交并推送更改到远程仓库。推送时出现了问题,如下:
红色字体给出问题:向远程仓库推送更改失败
浅黄色字体给出原因以及建议:①更新被拒绝是因为远程仓库中含有你本地没有的更改,通常是因为别人推送了更改。②在推送更改之前,你应该通过
git pull...
命令去继承远程仓库中的更改。
解决措施:
git fetch origin
将远程仓库中内容的更新同步到本地的远程追踪分支
- 在当前分支下执行命令
git merge origin/master
,目的是将远程追踪分支中的内容合并到当前分支,此时可能会产生冲突。(只有远程仓库中的新更改和当前分支中要推送的更改位于文件的不同一位置才不会产生冲突),此处由于更改的地方处于同一位置才产生了冲突:
- 解决冲突:此时需要打开B文件夹下的
a.txt
,进行选择性地修改
假如你需要远程仓库中的更改,那么进行如下修改:
假如你不需要远程仓库中的修改,那么进行如下修改:
- 在当前分支下,执行命令:
git add a.txt
–>git commit a.txt -m "合并远程仓库的master分支"
–>git push origin master
,将当前分支的代码推送到远程分支