文章

Git-Guide

#编程工具
本文目录 66

Git入门学习

目录

引言( Read me first !)

  • 介绍版本控制系统的概念及其重要性
  • Git的发展背景及其在行业中的地位
  • 文章的目标和结构概述
    • 本篇文章希望通过带你一步一步复现git中的操作,来更好地了解Git的功能与运用
    • 本文基于ubuntu22.04编写, 文件、目录的操作都是用bash命令完成,有些命令可能与windows的cmd命令有不同,也可以直接不用命令行操作,使用git的时候右击鼠标,选择“open git bash here ”

声明: 为了让没接触过Git的小伙伴能快速入门,在本文的前半部分以实际操作为主,可能有部分词汇不太严谨,更专业的说法以及原理将在后面呈现




Git 基础概念

如果光看概念没有太明白也不用担心,跟着接下来的实践能更好地理解Git

背景:集中式 vs 分布式

  • 集中式版本控制系统(CVCS)

    • 代表工具:SVN、CVS
    • 所有版本记录都保存在中央服务器上,开发者需要联网才能提交或更新代码。
    • 优点:管理集中,权限控制简单。
    • 缺点:依赖服务器,一旦服务器故障可能导致版本丢失;多人协作容易产生冲突。
  • 分布式版本控制系统(DVCS)

    • 代表工具:Git、Mercurial
    • 每个开发者的本地仓库都保存完整版本历史,操作大多在本地完成。
    • 优点:不依赖中央服务器、操作灵活、支持离线开发,容易进行分支和合并。
    • 缺点:初学者学习曲线稍陡,仓库可能体积大。

Git 核心概念

    +-------------------+
    |   远程仓库 (Remote) |
    |   origin/main      |
    +---------+---------+
              ^
              | git pull / fetch
              |
    +---------+---------+
    |  本地仓库 (Local)  |
    |  提交记录 Commit   |
    |  分支 Branch      |
    |  标签 Tag         |
    +---------+---------+
              ^
              | git commit
              |
    +---------+---------+
    |   暂存区 (Staging) |
    |  git add 文件到此处 |
    +---------+---------+
              ^
              | 修改文件
              |
    +---------+---------+
    |   工作区 (Working) |
    |  正在编辑的文件     |
    +-------------------+

Git 工作流程

Git 的工作目录大致分为四层:

  1. 工作目录(Working Directory)

    • 就是你平常看到的项目文件夹
    • 可以修改、编辑、删除文件
  2. 暂存区(Staging Area / Index)

    • 临时存放即将提交的文件
    • 通过 git add 将文件从工作区放入暂存区
  3. 本地仓库(Local Repository)

    • 通过 git commit 将暂存区的内容保存到本地仓库
    • 每次提交都会生成一个唯一 ID
  4. 远程仓库(Remote Repository)

    • 位于远程服务器(如 GitHub、GitLab)
    • 通过 git push 上传本地提交,通过 git pull 获取远程更新

本地的工作流程:主要在工作区、暂存区、本地仓库中进行 最主要的内容为:

  • 将工作区的文件添加到暂存区;
  • 将暂存区的文件添加到仓库;
  • 从仓库中恢复不同版本的文件 Git组成框架

但是划分成这三个区域究竟有什么用呢? 在图形化界面中,我们往往只能从资源管理器中看到工作区。也就是普通的目录 在这里插入图片描述

而我们的缓存区和仓库通常是储存在一个名为.git的隐藏文件夹里的 使用ls -a可以显示所有的目录 在这里插入图片描述 打开.git目录 在这里插入图片描述

那么文件夹里有这么多东西,又分别是用来干嘛的呢?

下面简单介绍一下 .git 文件夹里这些主要文件和目录的作用:


1. branches/

  • 作用:保存“本地分支和远程分支的映射关系”。
  • 但是这个目录在现代 Git 里基本上已经废弃了,几乎总是空的。 Git 现在用 refs/heads/ 和 refs/remotes/ 来管理分支。

2. config

  • 作用:当前仓库的配置文件。

  • 内容:存储仓库级别的 Git 配置,比如远程仓库地址、用户名邮箱、分支默认推送策略等。

  • 例子:

    [core]
        repositoryformatversion = 0
        filemode = true
    [remote "origin"]
        url = https://github.com/user/repo.git
        fetch = +refs/heads/*:refs/remotes/origin/*
    [branch "main"]
        remote = origin
        merge = refs/heads/main

3. HEAD 这一部分一定要耐心看到最后!很关键!

==分支==相关说明:

在 Git 中,分支实际上就是一个指向特定提交的可变指针。当你创建一个新分支时,Git 会创建一个新的指针来跟踪该分支的提交历史。

简单来说,提交是一个实在的物体,这个物体有它的id;而分支则是一个指针,指向某一次的提交,并会随着新的提交而移动

  • HEAD作用:一般来说指向 当前 检出的 分支(或具体的提交)。HEAD 是 Git 中一个特殊的指针,用于记录当前工作目录所处的状态。在大多数情况下,HEAD 相当于一个”你在这里”的标记,指向你正在工作的分支的最新提交。

    在一次新的提交中,创建的对象会以HEAD作为自己的父提交

上图更容易理解: 在这里插入图片描述

  • HEAD内容:

    • 如果你在某个分支上,也就是指向了这个分支,会是:

      ref: refs/heads/main
    • 如果你处于 游离 HEAD 状态(detached HEAD),比如checkout到了某一次提交,它会直接保存提交哈希:

      3f2a4e9b9d8f7a6c...

      这种状态下,后续的commit会游离在分支之外

这就像C++中的一个变量,以及指向这个变量的指针,以及指向指针的指针 ; 让我们用这张图来更清晰地认识一下游离的情况:

用checkout指令使HEAD指向提交C2 head


4. index

  • 作用:Git 的暂存区(staging area)。
  • 类型:是一个二进制文件(不是纯文本)。
  • 内容:记录哪些文件已经被 git add,以及对应的 文件快照哈希、路径、修改时间等。
  • Git 提交时就是根据 index 里的内容来生成新的 commit。

5. logs/

  • 作用:保存 Git 的操作日志(特别是分支引用的移动历史)。

  • 主要有:

    • logs/HEAD:记录 HEAD 每次切换或提交的移动。
    • logs/refs/heads/*:记录每个分支的提交历史(包括 rebase、reset)。
  • ⚠️ 和 git log 不一样,git log 只看提交历史;而 reflog(这些日志)能看到被删除或移动的提交(救命工具)。


6. packed-refs

  • 作用:保存“被打包的引用”(refs)。

  • 说明:Git 原本在 refs/heads/、refs/tags/ 下保存分支/标签,但如果分支和标签很多,Git 会把它们“打包”进 packed-refs 文件里,提升性能。

  • 例子:

    3f2a4e9b9d8f7a6cf5f39b2e2e2c1a commit refs/tags/v1.0
    8e9f7a6c3f2a4e9b9d8f7a6cf5f39b2e commit refs/tags/v1.1

7. description

  • 作用:仓库描述文件,主要给 GitWeb 这种 Web 界面用。

  • 默认内容:

    unnamed repository; edit this file 'description' to name the repository.
  • ⚠️ GitHub、GitLab 之类不用这个文件,它们用自己的数据库。


8. hooks/

  • 作用:保存 Git 钩子脚本。

  • 钩子 = Git 操作时触发的脚本,可以自定义自动化流程。

  • 常见钩子:

    • pre-commit:提交前执行(比如自动代码格式化)。
    • commit-msg:检查提交信息。
    • pre-push:推送前检查。
  • 默认是 .sample 结尾的示例脚本。


9. info/

  • 作用:存放仓库的补充信息。

  • 常见文件:

    • info/exclude:类似 .gitignore,但是只作用于当前仓库,不随仓库共享。 例如:

      *.log
      temp/

10. objects/

  • 作用:存放 Git 的所有 对象(Object),这是 Git 的核心。

  • Git 的一切数据(commit、tree、blob、tag)都是对象,按哈希值分目录存储。

  • 结构:

    objects/
      |-- ab/
      |     |-- cd1234...   # 对象文件
      |-- info/
      |-- pack/
            |-- pack-xxxx.idx
            |-- pack-xxxx.pack
  • 说明:

    • 松散对象:直接存储在 objects/xx/xxxxxx。
    • 打包对象(packfile):存储在 pack/ 里,多个对象压缩合并,提高性能。

11. refs/

  • 作用:存放所有引用(分支、标签、远程分支)。

  • 结构:

    refs/
      |-- heads/        # 本地分支
      |-- remotes/      # 远程分支
      |-- tags/         # 标签
  • 每个文件里就是一个 commit 的 id (哈希值)。

  • 例如 refs/heads/main 内容可能是:

    3f2a4e9b9d8f7a6c...

如果不是很明白别着急,可以跟着下面Git的基本操作完之后再回顾

而关于远程仓库,请看远程仓库协作部分




Git安装与配置

安装git

  • 在不同操作系统(Windows、macOS、Linux)上安装Git
    • Windows: git-for-windows下载 根据自己电脑的配置下载对应的版本:绝大多数笔记本都是x64架构 ; 安装时跟随指引正常勾选选项即可

    • Linux : 这里我以我的Ubuntu22为例 ,其他Linux发行版也同样是在bash里操作, CTRL + ALT + T 打开终端,输入:

sudo apt install git

可以查看git的版本来判断git是否安装成功

git --version

如果输出版本信息,则说明安装成功


配置git

  • 基本的Git配置:用户信息

当你第一次使用git的时候,我们需要设置以下你的用户信息邮箱、用户名 我们可以使用以下命令为我们的Git配置一下

git config --global user.name "你的用户名"
git config --global user.email "你的邮箱"

这里的命令config , 中文翻译过来就是配置的意思 命令参数 --global ,中文是全局变量,用来表示配置全部的git环境

  • 配置SSH密钥以连接远程仓库 首先需要注册一个github账号来进行以下的操作。具体原理请看 远程仓库协作


Git基本操作

我们首先从最简单的操作出发,再来解释背后发生的原理

初始化仓库:

我们可以使用git init 来初始化本地仓库,或者使用 git clone来将远程仓库克隆下来(见远程仓库协作)

这里我们以本地化为例, CTRL + ALT + T 打开终端 (如果是Windows,可以直接新建文件夹),输入:

  1. 创建一个名为testGit的文件夹
mkdir testGit
  1. 进入创建的目录
cd testGit
  1. 使用git init初始化
git init

在这里插入图片描述


文件状态管理:

最常见命令git status、git add、git commit、(git rm)

1.git status: “status”即状态的意思,该条命令用于查看当前的状态

我们首先在当前的目录创建一个文件,随后再执行status命令

touch test1.cpp
#创建一个cpp文件

git status

可以看到输出了如下图的状态

8

每一栏分别是:

  • On branch 现在在哪一条分支上
  • Commit state 提交的状态
  • Changes to be commited 缓存区未被提交的文件
  • untracked 工作区未被追踪的文件

2.git add 指定了你要在工作区追踪的文件 , add以后的文件会被储存在缓存区

我们不妨再创建一个文件,并查看状态

touch test2.cpp
#创建一个cpp文件

git status

在这里插入图片描述

这是我们可以看到,两个文件都没有被跟踪

我们使用add命令将test1加入缓存区,并再次查看状态

git add test1.cpp
git status

在这里插入图片描述 现在,test1.cpp已经成功地被追踪了,而test2.cpp还是未追踪状态

除了指定单个文件,add也可以指定所有的文件

git add --all
#或者是 add -A
git status

这样所有的文件都被追踪了 tracking-files

至于更多的指令选项,我们可以使用—help来查看, 请见Git/bash 帮助


3.git commit “commit”即提交的意思 ,可以将缓存区的文件提交到本地的仓库

我们使用commit命令将test提交 , -m是“message”的缩写,后面使用" "来键入这次提交的描述信息

git commit -m "commit test"
git status

可以看到,test已经成功提交了 在这里插入图片描述


4.git rm 如果我们直接从工作区中删除test2,可以看到本地仓库中test2仍然存在, 在这里插入图片描述 需要额外使用git add来追踪文件删除这一状态,再将删除commit到仓库 在这里插入图片描述

为此,可以直接使用git rm指令,将test2同时从工作区和仓库中删除 执行完之后可以看到ls没有输出,代表目录是空的 在这里插入图片描述



Git的‘版本控制’

而Git真正强大的地方在于 他会用一个生成的id来记录你所提交的每一个版本, 而我们可以使用这些id来回溯我们的代码,即进行版本控制 接下来我们学习如何查看提交历史,回滚历史记录


查看提交历史:git log 和 git show

使用git log来查看当前的历史提交记录 在这里插入图片描述

从图中可以看到我们的提交记录,每一行表示:

  • 某一次提交的id
  • 提交的作者
  • 提交的时间

我们也可以使用git log "filename"来查看某个特定文件的历史提交

touch test1.cpp
git add test1.cpp
git commit -m "test1"
#如果是按照刚才的操作来的 需要重建一下test1.cpp

git log test1.cpp

使用git show来查看最近一次提交的记录,或者指定查看的版本号和文件

git show 

#查看某个版本号的提交记录
git show <commit-hash>

#查看指定版本号、指定文件的提交记录
git show <commit-hash>:<file-path>

--- ·

撤销更改&回滚历史记录

git checkout、git reset、git revert

在开发过程中,我们经常会遇到以下几类需求:

  1. 丢弃未保存的修改(代码写错了,不想要了)。
  2. 撤销已经 add 到暂存区的内容。
  3. 回到某个历史版本(彻底重置)。
  4. 撤销某次错误提交,但保留历史记录(更安全)。

Git 提供了三种常用指令来处理:

  1. git checkout—— 丢弃工作区的修改

    1. 如果你改了某个文件,但还没执行 git add,
       可以用下面的命令恢复成最近一次提交的状态,
       这样文件会回到最后一次提交时的内容,未保存的修改会丢失。
git checkout -- <file>
    2.  而如果你已经执行了`git add `, 之后又修改了工作区的文件 ,
     工作区的文件会回到暂存区的状态

也就是说checkout — file 的本质是:用==暂存区覆盖工作区==。

如果暂存区里没有这个文件的改动,就用 HEAD(最近一次提交)的版本覆盖。


  1. git reset —— 回退到指定提交(可能丢历史)
git reset <选项> '回滚的id'

git reset 会改变当前分支的指向,让分支回到某个历史提交。 它有三种常见模式:

--soft

仅回退分支指针到指定提交 , 保留暂存区和工作区的修改 相当于 工作区、暂存区不变 , 仓库删除指定提交后面的版本

常用于:撤销提交,但想重新修改提交信息或合并到下一个提交


--mixed(默认模式)

回退分支指针,并清空暂存区

工作区文件保留,但变为“未暂存状态” 相当于 工作区不变,暂存区清空,仓库删除指定提交后面的版本

常用于:取消 git add

git reset --mixed <commit-hash>
git reset <commit-hash>   # 等价

--hard

回退分支指针,同时清空暂存区和工作区

所有未保存的修改都会丢失

常用于:彻底回退到某个版本

git reset --hard <commit-hash>

  1. git revert —— 撤销提交,但保留历史(推荐)

git revert 会生成一个新的提交,用来“抵消”指定的提交。这样历史记录不会丢失。

举例

# 当前分支提交历史
A -- B -- C (HEAD)

#假设 C 提交里写错了,我们执行:
git revert C


# 现在的分支提交历史
A -- B -- C -- D (HEAD)

# C 的提交记录仍然保留(历史不会丢失)。
# D 的内容正好把 C 里的修改“反向操作”掉。

适合在团队协作中撤销错误提交




分支与合并

在 Git 中,分支(branch) 是指向某个提交的可移动指针。 它的作用是让我们在主线开发之外,开辟出一条独立的开发路线,用于开发新功能、修复 bug,而不会影响主分支的稳定性。


1. 分支的概念及其重要性

  • 默认分支:新建仓库时会自动生成一个主分支(通常叫 main 或 master)。
  • 作用:通过分支,我们可以同时进行多条开发任务,比如一个分支写新功能,一个分支修 bug,互不干扰。
  • 优势:降低协作冲突风险,代码管理更清晰。

2. 创建和切换分支

  • 查看所有分支
git branch
  • 创建分支
git branch <branch-name>
# 创建的分支的父分支是当前分支,它继承了当前分支的所有文件
  • 切换分支
git checkout <branch-name>
# 切换分支之后,我们使用的命令就是在这条分支上进行操作了
  • 创建并切换分支
git checkout -b <branch-name>

3. 合并分支

当一个分支上的工作完成后,需要把它的修改合并到主分支:

git checkout main
#切换回主分支

git merge <branch-name>
#将修改合并
  • 如果两个分支没有冲突,会直接合并生成一个新的提交。
  • 如果修改了同一文件的同一位置,就会发生 冲突,需要手动编辑文件解决冲突,然后:
git add <file>
git commit

那么我们如何手动解决冲突呢?

那么我们如何手动解决冲突呢?具体步骤如下:

  1. 当合并出现冲突时,Git会在冲突文件中用特殊标记标出冲突区域:

    <<<<<<< HEAD
    当前分支的内容
    =======
    要合并分支的内容
    >>>>>>> branch-name
  2. 手动编辑文件,选择保留其中一个版本的内容,或者进行适当修改合并两种修改。需要完全删除<<<<<<<、=======和>>>>>>>这些标记行。

  3. 冲突解决后,使用git status命令可以查看哪些文件仍处于未合并状态。

  4. 对于每个解决完冲突的文件,都需要执行git add将其标记为已解决。

  5. 最后执行git commit完成合并。此时Git会自动生成合并提交信息,也可以使用-m参数自定义提交信息。

示例场景:假设你正在开发新功能,同事同时修改了同一个文件的同一部分。当你合并他的分支时就会遇到冲突,需要手动决定保留哪种修改,或者结合两种修改。(这一部分在接下来的远程仓库的PR中也也会提及~)


4. 变基操作(git rebase)

在 Git 里,每个提交都有一个 父提交(parent commit),表示它基于哪个版本修改的 这里不同分支之间的 父提交 在下图中用 \ 表示

git rebase 的作用是修改提交之间的父子关系, 把一个分支上的提交“搬运”到另一个分支的后面,让提交历史更加整洁。

例如:

main:    A -- B
          \
feature:   C -- D

执行:

git checkout feature
git rebase main

结果:

main:    A -- B
               \
feature:       C' -- D'
  • C、D 被重新“复制”成 C'、D',接在 B 之后。
  • 提交历史看起来像一条直线,更加清晰。

⚠️ 注意:rebase 会重写历史,不要在已经 推送到远程并被他人使用的分支 上使用。


5. 查看分支之间的区别

在 Git 中,我们经常需要比较不同分支之间的差异。以下是几种常用的分支比较方法:

5.1 比较两个分支的所有差异

使用 git diff 命令可以比较两个分支之间的所有差异:

git diff branch1..branch2

这个命令会显示两个分支之间所有不同的文件及其具体修改内容。例如:

  • 新增的文件会显示为绿色
  • 删除的文件会显示为红色
  • 修改的文件会显示具体的行变化

5.2 比较特定文件的差异

如果只想比较某个特定文件在两个分支中的差异:

git diff branch1..branch2 -- path/to/file

这在大型项目中特别有用,可以快速定位特定文件的变化。

5.3 查看提交历史差异

要查看两个分支之间的提交历史差异:

git log branch1..branch2

这会显示存在于 branch2 但不在 branch1 中的所有提交。如果想看双向差异,可以加上 --left-right 选项。

5.4 图形化比较工具

对于更直观的比较,可以使用图形化工具:

  • git difftool:调用配置的 diff 工具(如 Beyond Compare, KDiff3 等)
  • IDE 内置的版本控制工具(如 VS Code, IntelliJ IDEA 等)

5.5 查看分支合并情况

使用以下命令可以查看哪些分支已经合并或未合并到当前分支:

git branch --merged     # 显示已合并的分支
git branch --no-merged  # 显示未合并的分支

应用场景示例

  1. 代码审查:在合并分支前,先查看所有修改
  2. 冲突解决:定位两个分支的具体差异点
  3. 版本比较:比较不同版本间的功能差异
  4. 代码同步:确认哪些修改需要同步到其他分支

记住,在比较分支差异时,最好先确保本地分支是最新的(使用 git fetch 获取远程更新)。




远程仓库协作

常用操作:

  • 添加远程仓库:git remote add
  • 推送和拉取更改:git push 和 git pull
  • 克隆远程仓库:git clone
  • 协作流程:Fork、Pull Request(PR)

添加远程仓库

对于Git的远程仓库,现在使用最广泛的就是GitHub 我们现在将刚刚创建好的本地仓库上传

  1. 我们首先创建一个GitHub账号

  2. 配置本地的ssh

    ssh-keygen -t rsa -C "你的git账号"

    ssh是我们要建立的通讯协议的类型,keygen是”key generate”即“生成密钥”的缩写 -t是type即类型 , 这里指定的密钥类型是rsa -C是comment ,为生成的这个密钥进行了注释,方便区分

在这里插入图片描述

 #linux
 cd ~/.ssh
 ls
 =================================
 #Windows
 cd .ssh
 dir

这里可以看到.ssh文件夹里的文件,这两个是我们生成的私钥和公钥 ssh_ls 打开公钥文件

#Linux
cd .ssh              #进入.ssh目录
ls                   #列举所有的文件
cat github_ssh.pub   #打开公钥
====================================
#Linux
cd .ssh               #进入.ssh目录
dir                   #列举所有的文件
start github_ssh.pub  #打开公钥

在这里插入图片描述

  1. 连接到GitHub 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

  2. 检验ssh连接是否成功

ssh -T git@github.com

第一次会提示确认 GitHub 的主机指纹), 输入yes

The authenticity of host 'github.com (IP地址)' can't be established.
RSA key fingerprint is SHA256:xxxxxxxx...
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Hi 用户名! You've successfully authenticated, but GitHub does not provide shell access.

  1. 创建远程仓库

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

  1. 在目录里添加远程仓库(替换为你自己的仓库的ssh地址!)
cd testGit #打开目录
git remote add origin git@github.com:S1mpleWind/testGit.git #添加远程仓库

  1. 推送到远程仓库

使用git push命令 (建议先用status查看一下你的主分支是叫main还是master)

touch test.cpp
git add test.cpp
git commit -m "test"
git push origin master
#git push origin main 建议先用status
#从main/master分支(本地)推送到origin(远程)

回到github的页面,刷新之后就能看到文件上传成功了 在这里插入图片描述


  1. 在远程仓库中添加README.md , 用pull拉取更改

github会建议你创建一个README.md文件来介绍你的仓库,我们点击上一张图片中的Add a README, 随便输入一点之后 点击右上角的绿色commit change

创建完之后,可以使用pull来将远程仓库中新增的变化拉下来

git pull origin master
#git pull origin main

ls
#windows 不使用"ls",请使用 "dir"

可以看到README.md已经成功被拉取到了本地



克隆远程仓库

我们还可以直接把远程的仓库clone下来:

  1. 创建新的目录并进入
mkdir newTest
cd newTest
  1. 克隆已经存在的仓库
git clone git@github.com:S1mpleWind/testGit.git #替换成你自己的
  1. 检验是否克隆成功
ls
#ls指令是list的缩写,用于显示当前目录下的文件
#windows 不使用"ls",请使用 "dir"



创建PR(Pull Request)

当你在GitHub上与团队协作开发项目时,Pull Request(PR) 是一个核心的协作机制。它不仅是代码变更的提交方式,更是团队代码评审和讨论的重要平台。


PR的主要作用

  1. 代码合并请求:请求将你的分支(如feature/login)合并到目标分支(通常是main或master)
  2. 代码审查:团队成员可以查看你的变更,提出修改建议
  3. 持续集成:自动触发CI/CD流程,运行测试和构建
  4. 讨论平台:针对特定变更进行技术讨论

创建PR的标准流程

  1. 准备工作:

    • 确保本地分支是最新的(git pull)
    • 解决所有代码冲突
    • 通过本地测试
  2. 推送分支:

    git push origin your-branch-name
  3. 创建PR:

    • 在GitHub仓库页面点击”New pull request”按钮
    • 选择正确的源分支(你的分支)和目标分支
    • 填写清晰的标题和描述(建议使用模板)
  4. 完善PR信息:

    • 关联相关issue(使用”Closes #123”语法)
    • 添加适当的标签(如bug, enhancement)
    • 指定审阅者(reviewers)
  5. 持续更新:

    • 根据review意见修改后,直接push到原分支
    • PR会自动更新,无需新建

最佳实践

  • 保持PR规模适中(建议300行以内)
  • 一个PR只解决一个明确的问题
  • 提供清晰的修改背景和测试说明
  • 使用GitHub的预览功能检查变更

实际应用场景

示例:你开发了一个用户登录功能

  1. 在本地创建feature/login分支开发
  2. 完成开发后推送到远程仓库
  3. 创建PR请求合并到main分支
  4. 团队leader审查代码后提出优化建议
  5. 你修改后重新push,通过审查后合并

通过PR流程,团队可以确保代码质量,促进知识共享,并保持主分支的稳定性。### 创建PR(Pull Request) 当你在github上和你的团队进行协作的时候,PR往往是必不可少的一部分。它允许开发者将代码变更通知团队成员,请求将分支合并到主分支。

Git高级功能详解

1. 使用标签标记重要版本:git tag

Git标签是用于标记特定提交(如版本发布)的永久引用。与分支不同,标签创建后不会改变。标签分为两种类型:

  • 轻量标签(lightweight):只是一个指向特定提交的指针
  • 附注标签(annotated):存储为Git数据库中的完整对象,包含打标签者的名字、邮箱、日期和标签信息

常见用法示例:

# 创建轻量标签
git tag v1.0.0

# 创建附注标签(-a)并添加消息(-m)
git tag -a v1.1.0 -m "Release version 1.1.0 with new features"

# 查看所有标签
git tag

# 查看标签详情
git show v1.0.0

# 将标签推送到远程仓库
git push origin v1.0.0

使用tag能很好的帮你标记在开发过程中迭代版本的代码


2. 暂存更改:git stash

git stash命令用于临时保存工作目录和暂存区的修改,而不需要提交。这在需要快速切换分支但当前工作未完成时特别有用。

详细用法:

# 保存当前工作状态(包括未跟踪的文件)
git stash save "work in progress"

# 查看存储的stash列表
git stash list

# 恢复最近保存的stash并删除stash记录
git stash pop

# 恢复指定stash但不删除记录
git stash apply stash@{1}

# 删除特定stash
git stash drop stash@{1}

# 清除所有stash记录
git stash clear

3. 交互式暂存:git add -p

交互式暂存允许你选择性地暂存文件的特定部分,而不是整个文件。这对于将大改动分解为逻辑上独立的提交非常有用。

操作步骤:

  1. 运行git add -p或git add --patch
  2. Git会显示每个改动”块”(hunk)并询问操作:
    • y: 暂存该块
    • n: 不暂存该块
    • q: 退出
    • s: 分割当前块为更小的块
    • e: 手动编辑当前块
  3. 重复此过程直到完成所有选择

示例场景: 当你在一个文件中同时修复了两个bug,可以使用交互式暂存将它们分别提交:

git add -p bugfix.py
# 选择第一个bug相关的改动块
git commit -m "Fix issue #123"
git add -p bugfix.py
# 选择第二个bug相关的改动块
git commit -m "Fix issue #456"

4. 子模块管理:git submodule

子模块允许你将一个Git仓库作为另一个Git仓库的子目录,保持它们的独立性但又能协同工作。

常用命令:

# 添加子模块
git submodule add https://github.com/user/repo.git path/to/submodule

# 克隆包含子模块的仓库
git clone --recurse-submodules https://github.com/user/main-repo.git

# 或克隆后初始化子模块
git submodule init
git submodule update

# 更新子模块到最新提交
git submodule update --remote

# 查看子模块状态
git submodule status

管理技巧:

  • 子模块有自己的.git目录,存储自己的提交历史
  • 主项目只记录子模块的特定提交,不跟踪其内容变化
  • 修改子模块后需要在主项目中提交子模块引用变更
  • 使用--recursive选项时,递归操作会应用到所有嵌套子模块

应用场景:

  • 将共享库作为子模块包含在多个项目中
  • 分离核心代码和依赖组件
  • 管理大型项目中的独立功能模块# Git高级功能
  • 使用标签标记重要版本:git tag
  • 暂存更改:git stash
  • 交互式暂存:git add -p
  • 子模块管理:git submodule


Git 指令的基本范式

Git 的命令和普通的bash命令一样,通常遵循以下结构:

git <指令> [选项] [参数]

  • 指令(Command):表示要执行的具体操作,例如 clone、commit、push。
  • 选项(Option):用于调整指令的执行方式,通常以 - 或 — 开头,例如 -m、—all。
  • 参数(Argument):指令或选项所作用的对象,例如文件路径、分支名、提交 ID 等。

例如:

git commit -m "初始化项目"

其中:

commit 是指令;

-m 是选项;

“初始化项目” 是参数。

这样可以更清晰地理解 Git 命令的组成与用法。

如果想要每一条指令具体的选项和参数,可以使用--help选项来查看

    git commit --help


Git最佳实践

  • 提交信息的规范(如Conventional Commits)
  • 分支管理策略(如Git Flow、GitHub Flow)
  • 避免常见错误(如强制推送、大文件提交)

常见问题与解决方案

如何撤销错误的提交

  1. 撤销本地未推送的提交

    • 使用 git reset --soft HEAD~1 保留更改但撤销提交
    • 使用 git reset --hard HEAD~1 彻底丢弃更改
    • 示例:git reset --soft HEAD~1 && git commit -m "正确的提交信息"
  2. 撤销已推送的提交

    • 使用 git revert <commit-hash> 创建反向提交
    • 适用于共享仓库的撤销
    • 示例:git revert abc1234 然后推送反向提交
  3. 修改最近一次提交

    • git commit --amend 修改提交信息或内容
    • 适用于仅修改最后一次提交的情况

如何恢复误删的分支

  1. 查找删除的分支记录

    • git reflog 查看所有操作历史
    • 查找删除前的commit记录
  2. 恢复分支方法

    • 通过commit hash恢复:git branch <branch-name> <commit-hash>
    • 示例:git branch feature/login abc1234
  3. 预防措施

    • 推送分支到远程:git push origin <branch-name>
    • 定期备份重要分支

如何处理大文件或敏感信息

  1. 大文件处理方案

    • 使用Git LFS (Large File Storage)
    • 安装后配置:git lfs install
    • 跟踪大文件:git lfs track "*.psd"
  2. 移除已提交的敏感信息

    • 使用 git filter-branch 或 BFG Repo-Cleaner
    • 示例:bfg --replace-text passwords.txt my-repo.git
    • 完成后强制推送:git push --force
  3. 预防措施

    • 添加.gitignore文件排除特定文件
    • 使用环境变量存储敏感信息
    • 定期检查仓库中的大文件:git count-objects -vH# 常见问题与解决方案


工具与扩展

图形化工具

  • GitHub Desktop:微软开发的跨平台Git图形界面,特别适合GitHub用户,提供直观的提交历史查看、分支管理和冲突解决界面
  • SourceTree:Atlassian推出的免费Git客户端,支持Windows和Mac,提供强大的可视化分支管理功能
  • GitKraken:流行的跨平台Git客户端,具有漂亮的UI设计和丰富的功能集,包括内置合并工具和GitFlow支持

IDE中的Git集成

  • VS Code:内置Git支持,提供源代码管理面板、差异查看器和提交界面,可通过扩展(如GitLens)增强功能
  • IntelliJ IDEA:提供完整的Git集成,包括可视化提交、分支管理和冲突解决工具,支持GitFlow工作流
  • Eclipse:通过EGit插件提供Git支持,包括提交历史查看、分支管理和远程仓库操作

第三方服务

  • GitHub:最流行的Git托管平台,提供代码托管、协作工具和CI/CD集成,支持GitHub Actions自动化
  • GitLab:开源Git平台,提供完整的DevOps工具链,包括CI/CD、容器注册表和项目管理功能
  • Bitbucket:Atlassian的Git解决方案,与Jira深度集成,适合企业开发团队
  • Azure DevOps:微软的企业级Git托管服务,提供完整的ALM工具链和CI/CD流水线

其他实用工具

  • Tower:macOS平台的付费Git客户端,提供直观的界面和强大的功能
  • Fork:轻量级的Git客户端,专注于性能和用户体验
  • Git-Cola:开源的跨平台Git图形界面,适合Linux用户


结语

Git的核心价值总结

Git作为分布式版本控制系统,其核心价值主要体现在以下几个方面:

  1. 版本控制能力:Git可以精确记录文件的历史变更,包括谁在什么时候修改了什么内容,形成了完整的开发历史记录。

  2. 分布式架构:每个开发者都拥有完整的仓库副本,可以在离线状态下工作,大大提高了开发灵活性和可靠性。

  3. 分支管理优势:Git的轻量级分支模型使得创建、合并和管理分支变得极其简单,支持高效的并行开发流程。

  4. 数据完整性保障:采用SHA-1哈希算法确保所有提交和文件内容都是不可篡改的,为代码提供了可靠的安全保障。

  5. 高效性能:大多数操作都在本地完成,响应速度快,能够轻松处理大型项目和复杂的历史记录。

学习资源推荐

官方文档

在线课程

推荐书籍

  • 《Pro Git》(Scott Chacon著):Git核心开发团队成员编写,内容全面且深入。
  • 《Git权威指南》(蒋鑫著):中文Git经典教程,适合中国开发者阅读。
  • 《Version Control with Git》(Jon Loeliger著):侧重实际工作场景中的Git使用技巧。

鼓励实践与进一步探索

Git的学习需要通过大量实践才能真正掌握。建议:

  1. 创建个人项目仓库:用Git管理自己的个人项目,如博客、小程序等,从简单的版本控制开始练习。

  2. 参与开源项目:通过GitHub等平台参与开源项目,体验团队协作开发流程,学习如何处理合并请求和解决冲突。

  3. 尝试高级功能:当熟悉基础操作后,可以探索Git的高级功能,如:

    • 交互式rebase
    • 子模块管理
    • 钩子脚本
    • 二分查找定位问题提交
  4. 持续学习新技术:Git生态系统不断发展,可以关注Git LFS(大文件存储)、Git Flow等工作流程,以及Git与其他DevOps工具的集成。

记住,Git是一个工具,最重要的是理解其背后的设计理念和工作原理,这样才能灵活应对各种复杂场景。祝你在Git的学习和使用中不断进步!

欢迎大佬们的批评指正