Git完全入门指南-从概念到实战掌握版本控制的核心
🌈 say-fall:个人主页 🚀 专栏:《手把手教你学会C++》 | 《系统深入Linux操作系统》 | 《数据结构与算法》 | 《小游戏与项目》 💪 格言:做好你自己,才能吸引更多人,与他们共赢,这才是最好的成长方式。
📝 前言
你是否曾经因为代码修改失误而无法恢复?是否曾经为了管理不同版本的代码而创建了无数个"最终版"、"绝对最终版"、"真的最终版"的文件夹?是否曾经在团队协作时因为代码合并而焦头烂额?
如果你的答案是肯定的,那么 Git 就是解决这些问题的终极武器。
在软件开发的世界里,版本控制是每个开发者必备的核心技能。没有版本控制工具的年代,开发者们管理代码的方式极其原始且低效------复制文件夹、手动合并、误删丢失......这些噩梦相信你或多或少都经历过。而 Git 的出现,彻底改变了这一切。
本文将从 为什么需要版本控制 讲起,深入剖析 Git 的核心优势、基本概念、架构原理,再到每一个指令的详细用法,最后覆盖团队协作中的冲突解决等实战场景。无论你是刚接触 Git 的小白,还是想系统梳理知识的开发者,这篇文章都能给你带来实实在在的收获。
通过本文,你将掌握:
| 技能 | 应用场景 |
|---|---|
| 理解 Git 分布式架构与三大区域模型 | 从根本上理解 Git 的工作原理 |
| 熟练使用 git add / commit / push 等核心指令 | 日常开发的版本管理工作流 |
| 掌握分支管理、冲突解决、.gitignore 配置 | 团队协作与项目管理的必备能力 |
| 了解 Git 的历史背景与设计哲学 | 更深入地理解为什么要这样用 Git |
📌 前置知识: 本文面向所有对 Git 感兴趣的读者,无需任何前置基础,从零开始带你掌握 Git。
文章目录
- [Git完全入门指南-从概念到实战掌握版本控制的核心](#pic_center =100x100))
-
- [📝 前言](#📝 前言)
- 一、为什么我们需要版本控制?
-
- [1.1 没有版本控制的"黑暗时代"](#1.1 没有版本控制的"黑暗时代")
- [1.2 版本控制系统的诞生](#1.2 版本控制系统的诞生)
- [二、Git 的优势:为什么选择 Git 而不是其他?](#二、Git 的优势:为什么选择 Git 而不是其他?)
-
- [2.1 🏗️ 完全分布式架构 ------ Git 最核心的优势](#2.1 🏗️ 完全分布式架构 —— Git 最核心的优势)
- [2.2 ⚡ 惊人的速度](#2.2 ⚡ 惊人的速度)
- [2.3 🌿 强大的分支管理](#2.3 🌿 强大的分支管理)
- [2.4 🔒 数据完整性](#2.4 🔒 数据完整性)
- [2.5 📦 只存储变化的部分(增量存储)](#2.5 📦 只存储变化的部分(增量存储))
- [三、Git 的诞生故事](#三、Git 的诞生故事)
- [四、Git 的基本概念与架构](#四、Git 的基本概念与架构)
-
- [4.1 Git 的三个工作区域](#4.1 Git 的三个工作区域)
-
- [① 工作区(Working Directory)](#① 工作区(Working Directory))
- [② 暂存区(Staging Area / Index)](#② 暂存区(Staging Area / Index))
- [③ 本地仓库(Local Repository / .git 目录)](#③ 本地仓库(Local Repository / .git 目录))
- [④ 远程仓库(Remote Repository)](#④ 远程仓库(Remote Repository))
- [4.2 文件的四种状态](#4.2 文件的四种状态)
- [4.3 提交(Commit)------ Git 的基本单位](#4.3 提交(Commit)—— Git 的基本单位)
- [4.4 分支(Branch)------ 只是一个指针!](#4.4 分支(Branch)—— 只是一个指针!)
- [五、Git 的安装和配置](#五、Git 的安装和配置)
-
- [5.1 安装 Git](#5.1 安装 Git)
- [5.2 首次使用配置 ------ 全局身份设置](#5.2 首次使用配置 —— 全局身份设置)
- [六、Git 的基本工作流程 ------ "三板斧"](#六、Git 的基本工作流程 —— "三板斧")
-
- [步骤 1:创建一个新的本地仓库](#步骤 1:创建一个新的本地仓库)
- [步骤 2:创建并修改文件](#步骤 2:创建并修改文件)
- [步骤 3:将文件添加到暂存区(git add)](#步骤 3:将文件添加到暂存区(git add))
- [步骤 4:将暂存区的修改提交到本地仓库(git commit)](#步骤 4:将暂存区的修改提交到本地仓库(git commit))
- [步骤 5:将本地仓库推送到远程仓库(git push)](#步骤 5:将本地仓库推送到远程仓库(git push))
- [七、Git 常用命令详解](#七、Git 常用命令详解)
-
- [7.1 查看仓库状态 ------ `git status`](#7.1 查看仓库状态 ——
git status) - [7.2 查看提交历史 ------ `git log`](#7.2 查看提交历史 ——
git log) - [7.3 克隆远程仓库 ------ `git clone`](#7.3 克隆远程仓库 ——
git clone) - [7.4 从远程仓库拉取代码 ------ `git pull`](#7.4 从远程仓库拉取代码 ——
git pull) - [7.5 查看文件修改内容 ------ `git diff`](#7.5 查看文件修改内容 ——
git diff) - [7.6 撤销修改 ------ Git 的"后悔药"](#7.6 撤销修改 —— Git 的"后悔药")
-
- [场景 1:工作区修改了,想丢弃(未执行 git add)](#场景 1:工作区修改了,想丢弃(未执行 git add))
- [场景 2:已经 git add 了,想撤出暂存区](#场景 2:已经 git add 了,想撤出暂存区)
- [场景 3:已经 git commit 了,想撤销这次提交](#场景 3:已经 git commit 了,想撤销这次提交)
- [7.7 删除文件 ------ `git rm`](#7.7 删除文件 ——
git rm) - [7.8 重命名文件 ------ `git mv`](#7.8 重命名文件 ——
git mv)
- [7.1 查看仓库状态 ------ `git status`](#7.1 查看仓库状态 ——
- 八、远程仓库操作详解
-
- [8.1 查看远程仓库](#8.1 查看远程仓库)
- [8.2 添加远程仓库](#8.2 添加远程仓库)
- [8.3 删除远程仓库关联](#8.3 删除远程仓库关联)
- [8.4 重命名远程仓库](#8.4 重命名远程仓库)
- [8.5 获取远程更新但不合并 ------ `git fetch`](#8.5 获取远程更新但不合并 ——
git fetch)
- [九、冲突解决 ------ 团队协作必经之路](#九、冲突解决 —— 团队协作必经之路)
-
- [9.1 冲突是如何发生的?](#9.1 冲突是如何发生的?)
- [9.2 冲突发生时的现象](#9.2 冲突发生时的现象)
- [9.3 冲突标记详解](#9.3 冲突标记详解)
- [9.4 解决冲突的步骤](#9.4 解决冲突的步骤)
- [十、.gitignore 文件 ------ 告诉 Git 忽略什么](#十、.gitignore 文件 —— 告诉 Git 忽略什么)
-
- [10.1 常见需要忽略的文件类型](#10.1 常见需要忽略的文件类型)
- [10.2 .gitignore 语法规则](#10.2 .gitignore 语法规则)
- [10.3 一个典型的 C/C++ 项目 .gitignore](#10.3 一个典型的 C/C++ 项目 .gitignore)
- [十一、GitHub 完整工作流](#十一、GitHub 完整工作流)
-
- [11.1 首次使用的完整流程](#11.1 首次使用的完整流程)
- [11.2 日常开发循环](#11.2 日常开发循环)
- [11.3 团队协作循环](#11.3 团队协作循环)
- [十二、🤔 几个思考题](#十二、🤔 几个思考题)
-
- [1️⃣ Git 和 SVN 的本质区别是什么?](#1️⃣ Git 和 SVN 的本质区别是什么?)
- [2️⃣ `git add`、`git commit`、`git push` 分别操作的是哪个区域?](#2️⃣
git add、git commit、git push分别操作的是哪个区域?) - [3️⃣ `git fetch` 和 `git pull` 有什么区别?什么时候该用哪个?](#3️⃣
git fetch和git pull有什么区别?什么时候该用哪个?) - [4️⃣ 什么时候会产生冲突?如何避免?](#4️⃣ 什么时候会产生冲突?如何避免?)
- [5️⃣ `.gitignore` 文件应该放在哪里?什么时候创建最好?](#5️⃣
.gitignore文件应该放在哪里?什么时候创建最好?)
- 总结
一、为什么我们需要版本控制?
1.1 没有版本控制的"黑暗时代"
在没有版本控制工具的年代,开发者们管理代码的方式极其原始。想象一下这个痛苦的场景:
- 你正在开发一个项目,为了保留不同阶段的代码,你创建了 "项目-v1"、"项目-v2"、"项目-修复bug版"、"项目-最终版"、"项目-真的最终版" 等一系列文件夹
- 当你需要回到某个特定版本时,不得不一个个打开文件夹查找
- 当团队成员同时修改同一个文件时,需要手动合并代码,很容易出现冲突和错误
- 一旦某个文件被误删或修改,你可能永远失去了之前的工作成果
文档如此,我们写的项目代码也存在完全一样的问题!随着版本数量不断增多,你还记得这些版本各自都改了什么吗?
1.2 版本控制系统的诞生
**版本控制系统(Version Control System, VCS)**的出现彻底改变了这一现状。它可以:
- ✅ 记录文件的每一次修改------让你可以随时回到任何一个历史版本
- ✅ 追踪谁在什么时候修改了什么内容------方便代码审查和问题定位
- ✅ 支持多人并行开发------自动合并不同开发者的修改
- ✅ 提供分支功能------让你可以在不影响主线代码的情况下开发新功能或修复 bug
通俗来说,版本控制器就是一个能让你了解一个文件的历史以及它发展过程的系统------是一个可以记录工程的每一次改动和版本迭代的管理系统,同时方便多人协同作业。
目前最主流的版本控制系统就是 Git。Git 可以控制电脑上所有格式的文件(doc、excel、dwg 等),对于我们开发人员来说,Git 最重要的是帮助我们管理软件开发项目中的源代码文件!
二、Git 的优势:为什么选择 Git 而不是其他?
Git 是目前世界上最先进、最流行的分布式版本控制系统(Distributed VCS)。与传统的集中式版本控制系统(如 SVN、CVS)相比,Git 具有以下不可替代的优势:
2.1 🏗️ 完全分布式架构 ------ Git 最核心的优势
这是 Git 与 SVN/CVS 等传统工具最本质的区别。
在集中式版本控制系统中:
- 所有的代码历史都存储在中央服务器上
- 开发者只能从中央服务器获取代码,修改后再提交回去
- ❌ 如果中央服务器宕机或网络中断 → 所有开发者都无法工作
- ❌ 单点故障风险极高
而 Git 采用了完全分布式的架构:
┌─────────────────────────────────────────────────────┐
│ Git 分布式架构 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 开发者 A │ │ 开发者 B │ │ 开发者 C │ │
│ │ │ │ │ │ │ │
│ │ 本地仓库 │ │ 本地仓库 │ │ 本地仓库 │ │
│ │(完整历史) │ │(完整历史) │ │(完整历史) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ │ push/pull │ push/pull │ │
│ └────────┬───────┴────────┬───────┘ │
│ ▼ ▼ │
│ ┌─────────────────────────┐ │
│ │ 远程仓库 (GitHub) │ │
│ │ │ │
│ └─────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
每个开发者的本地计算机上都有一个完整的代码仓库,包含了所有的历史记录。这意味着:
- 🌐 开发者可以在没有网络连接的情况下继续工作,提交代码到本地仓库
- 🔄 当网络恢复后,再将本地的提交同步到远程仓库
- 💾 即使远程仓库损坏,任何一个开发者的本地仓库都可以作为完整的备份
- ⚡ 大部分操作都在本地完成,不需要网络通信
2.2 ⚡ 惊人的速度
Git 的设计目标之一就是速度。由于几乎所有的操作都可以在本地完成(不需要与远程服务器通信),Git 的操作速度非常快:
git commit------ 瞬间完成(只操作本地)git branch------ 毫秒级(只是创建一个指针)git log------ 极快(直接读取本地数据库)git diff------ 极快(本地差异计算)
特别是在处理大型项目(如 Linux 内核这种超大规模项目)时,Git 的速度优势更加明显。
2.3 🌿 强大的分支管理
Git 的分支管理功能是其最引以为傲的特性之一。在 Git 中,创建和合并分支几乎是瞬间完成的,成本极低。
这使得开发者可以:
- 为每个新功能创建一个独立的分支,开发完成后再合并到主线
- 为修复 bug 创建临时分支,修复完成后合并并删除
- 同时维护多个版本的代码,如开发版、测试版、稳定版
💡 Git 允许成千上万个并行开发的分支!这是当初 Linus Torvalds 设计 Git 时的核心目标之一。
2.4 🔒 数据完整性
Git 使用 SHA-1 哈希算法 来标识文件和提交。每个提交都有一个唯一的 40 位十六进制哈希值 (类似 a5a8f007f4c8e39d8cfc1d0c5c7fe8a8b3e6d9f2),这个哈希值是基于提交的内容和元数据计算出来的。
- 一旦提交被创建,它的哈希值就永远不会改变
- 任何对数据的修改都会导致哈希值的变化
- 这确保了 Git 中的数据不会被篡改
2.5 📦 只存储变化的部分(增量存储)
当你提交代码时,Git 不会保存整个文件的副本,而是只保存自上次提交以来发生变化的部分(delta)。这大大节省了存储空间,特别是对于大型项目来说。
三、Git 的诞生故事
了解 Git 的历史,有助于我们理解它的设计哲学。
同生活中的许多伟大事物一样,Git 诞生于一个极富纷争又举创新的年代:
- 1991--2002 年间:Linux 内核开源项目的绝大多数维护工作花在了提交补丁和保存归档的繁琐事务中
- 2002 年 :整个项目组开始启用专有的分布式版本控制系统 BitKeeper 来管理和维护代码
- 2005 年 :开发 BitKeeper 的商业公司同 Linux 内核开源社区结束合作,收回了免费使用权
这迫使 Linux 社区(特别是 Linux 之父 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。他们对新系统制订了若干目标:
| 目标 | 说明 |
|---|---|
| ⚡ 速度 | 所有操作必须极速 |
| 🎯 简单的设计 | 设计应当简洁直观 |
| 🌿 对非线性开发模式的强力支持 | 允许成千上万个并行开发的分支 |
| 🌐 完全分布式 | 每个开发者都有完整的历史 |
| 💪 高效管理超大规模项目 | 如 Linux 内核 |
自 2005 年诞生以来,Git 日臻成熟完善,在高度易用的同时仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。
四、Git 的基本概念与架构
在开始使用 Git 之前,我们必须深入理解几个核心概念。这些概念是理解 Git 工作原理的基础。
4.1 Git 的三个工作区域
Git 的核心架构围绕三个区域展开,理解了这三个区域,你就理解了 Git 的一半:
┌──────────────────────────────────────────────────────────────┐
│ Git 三区架构图 │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ git add ┌──────────────┐ │
│ │ │ ──────────────▶ │ │ │
│ │ 工作区 │ │ 暂存区 │ │
│ │ (Working Dir) │ ◀────────────── │ (Staging Area)│ │
│ │ │ git checkout │ (Index) │ │
│ └──────────────┘ └──────┬───────┘ │
│ │ │
│ git commit │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ │ │
│ │ 本地仓库 │ │
│ │ (.git dir) │ │
│ │ │ │
│ └──────┬───────┘ │
│ │ │
│ git push │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ │ │
│ │ 远程仓库 │ │
│ │ (Remote) │ │
│ │ │ │
│ └───────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
① 工作区(Working Directory)
工作区就是你在计算机上看到的项目目录,包含了所有的项目文件。你在工作区中对文件进行修改、添加、删除等操作。
📍 你平时编辑代码的地方就是工作区。
② 暂存区(Staging Area / Index)
暂存区是一个临时存储区域,用于保存你即将提交的修改。你可以把它理解为"待提交清单"------告诉 Git 哪些修改要包含在下一次提交中。
📍 使用
git add命令时,就是把工作区的修改添加到暂存区。
③ 本地仓库(Local Repository / .git 目录)
本地仓库是你计算机上的 Git 数据库,存储在项目根目录下的 .git 隐藏目录中。它包含了:
- 项目的所有历史记录(每一次提交的快照)
- 分支信息(各个分支指向哪个提交)
- 配置信息(用户名、远程仓库地址等)
📍 使用
git commit命令时,就是把暂存区的修改永久记录到本地仓库。
④ 远程仓库(Remote Repository)
远程仓库是存储在网络服务器上的 Git 仓库(如 GitHub、Gitee、GitLab),用于:
- 👥 团队协作------多人共享代码
- ☁️ 代码备份------防止本地数据丢失
- 🚀 开源发布------向世界展示你的项目
📍 使用
git push命令时,就是把本地仓库的推送到远程仓库;git pull则是从远程拉取更新。
4.2 文件的四种状态
根据文件所处的区域,Git 中的文件有四种状态:
| 状态 | 含义 | 所在区域 |
|---|---|---|
| Untracked(未跟踪) | 新文件,Git 还没管理它 | 工作区 |
| Unmodified(未修改) | 已被 Git 管理,但当前没有改动 | 工作区 |
| Modified(已修改) | 文件被改动了,但还没放到暂存区 | 工作区 |
| Staged(已暂存) | 文件已放入暂存区,等待提交 | 暂存区 |
状态转换关系:
Untracked ──git add──▶ Staged ──git commit──▶ Unmodified
▲ │
│ (编辑文件) │
│ ▼
└──────── Modified ◀───────────┘
│
git add
▼
Staged
4.3 提交(Commit)------ Git 的基本单位
提交是 Git 中的基本单位,代表了项目在某个时间点的快照。每个提交都包含以下信息:
| 组成部分 | 说明 |
|---|---|
| SHA-1 哈希值 | 唯一的 40 位十六进制标识符(如 a5a8f007...) |
| 作者信息 | 提交者的姓名和邮箱 |
| 提交时间 | 精确到秒的时间戳 |
| 提交信息 | 描述本次提交的内容(由你自己写) |
| 父提交指针 | 指向上一次提交(形成链表结构) |
| 树对象 | 本次提交时整个项目目录的快照 |
4.4 分支(Branch)------ 只是一个指针!
这是初学者最容易误解的概念:Git 的分支本质上就是一个指向某个提交的可移动指针。
-
Git 默认创建的分支叫做
master(现在很多项目已改为main) -
当你创建一个新分支时,Git 只是创建了一个新的指针,并没有复制任何文件!
-
这就是为什么 Git 创建分支的速度如此之快------因为它只需要创建一个 41 字节的文件(40 字符哈希 + 换行)
主分支 main: ● ←──── C3 (HEAD)
│
● ←──── C2
│
● ←──── C1创建分支 feature 后:
main: ● ←──── C3 (HEAD)
│
● ←──── C2
│
feature: ● ←──── C1
↑
只是多了一个指针!没有复制任何文件!
五、Git 的安装和配置
5.1 安装 Git
在不同的操作系统上,安装 Git 的方法略有不同:
CentOS / RHEL 系统:
bash
sudo yum install git -y
Ubuntu / Debian 系统:
bash
sudo apt install git -y
Windows 系统:
从 Git 官方网站(https://git-scm.com/ )下载安装程序,按照提示进行安装。建议一路默认选项即可。
macOS 系统:
bash
brew install git
安装完成后,可以通过以下命令验证 Git 是否安装成功:
bash
$ git --version
git version 2.x.x
如果成功显示版本号,说明 Git 已经正确安装在你的系统上了。
5.2 首次使用配置 ------ 全局身份设置
在使用 Git 之前,你必须配置用户名和邮箱地址。这些信息会出现在你的每一次提交中,用于标识提交者的身份。
bash
# 设置全局用户名(--global 表示对所有仓库生效)
git config --global user.name "Your Name"
# 设置全局邮箱
git config --global user.email "your.email@example.com"
⚠️ 这个配置非常重要!每次 commit 都会记录这个信息,一旦提交后就不可更改(虽然可以用 amend 修正,但不建议频繁使用)。请务必填写真实信息。
关键参数说明:
| 参数 | 含义 |
|---|---|
--global |
表示这个配置对当前用户的所有 Git 仓库都有效 |
不带 --global |
只对当前仓库有效(需要在仓库目录内执行) |
查看你的配置:
bash
$ git config --list
user.name=Your Name
user.email=your.email@example.com
...
其他常用配置项:
bash
# 设置默认分支名称为 main
git config --global init.defaultBranch main
# 设置默认文本编辑器(用于编写提交信息)
git config --global core.editor "code --wait"
# 开启颜色输出(让命令行输出更易读)
git config --global color.ui auto
六、Git 的基本工作流程 ------ "三板斧"
Git 的基本工作流程可以概括为四个步骤,这就是著名的 "Git 三板斧":
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 修改文件 │ ──▶ │ git add │ ──▶ │git commit│ ──▶ │ git push │
│ (工作区) │ │ (暂存) │ │ (提交) │ │ (推送) │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
下面我们通过一个完整的实际例子来演示这个流程。
步骤 1:创建一个新的本地仓库
首先,创建一个新的项目目录,并进入该目录:
bash
$ mkdir myproject
$ cd myproject
然后,使用 git init 命令将这个目录初始化为一个 Git 仓库:
bash
$ git init
Initialized empty Git repository in /home/user/myproject/.git/
💡 这个命令会在当前目录下创建一个名为
.git的隐藏目录,这个目录包含了 Git 仓库的所有元数据和历史记录。千万不要手动修改或删除这个目录!
步骤 2:创建并修改文件
在项目目录中创建一个新的文件,例如 README.md:
bash
$ echo "# My Project" > README.md
此时,这个文件处于 Untracked(未跟踪) 状态------Git 知道它的存在,但不会跟踪它的变化。
步骤 3:将文件添加到暂存区(git add)
使用 git add 命令将文件添加到暂存区:
bash
$ git add README.md
git add 的多种用法:
| 命令 | 含义 |
|---|---|
git add <文件名> |
将指定文件添加到暂存区 |
git add . |
将当前目录下所有修改添加到暂存区(含新增、修改、删除) |
git add *.c |
将所有 .c 后缀的文件添加到暂存区 |
git add -A |
添加所有变化(等同于 git add .) |
git add -p |
交互式暂存------逐块选择要不要暂存(高级但非常有用!) |
💡
git add不是"添加文件"的意思,而是"把文件的当前快照加入待提交列表"。你可以反复修改一个文件,然后用git add把你想提交的那个版本加入暂存区。
步骤 4:将暂存区的修改提交到本地仓库(git commit)
使用 git commit 命令将暂存区中的修改永久记录到本地仓库:
bash
$ git commit -m "Initial commit"
[master (root-commit) a5a8f00] Initial commit
1 file changed, 1 insertion(+)
create mode 100644 README.md
参数详解:
| 参数 | 含义 |
|---|---|
-m "message" |
直接指定提交信息(推荐方式) |
不带 -m |
打开文本编辑器(vim/nano)让你输入提交信息 |
提交输出的含义解读:
[master (root-commit) a5a8f00] Initial commit
│ │ │ │
│ │ │ └── 提交信息(你写的内容)
│ │ └── 本次提交的哈希值(前7位)
│ └── root-commit 表示这是该仓库的第一个提交
└── 当前所在分支名
1 file changed, 1 insertion(+)
│ │
│ └── 新增了1行内容
└── 有1个文件发生变化
⚠️ 提交信息应该简洁明了地描述本次提交做了什么。好的提交信息示例:"fix: 修复登录页验证码不显示的问题",不好的示例:"改了一些东西"。
步骤 5:将本地仓库推送到远程仓库(git push)
首先,你需要在 GitHub 或 Gitee 上创建一个新的远程仓库。创建完成后,你会得到一个远程仓库的 URL。
① 关联远程仓库:
bash
$ git remote add origin https://github.com/yourusername/myproject.git
| 部分 | 含义 |
|---|---|
git remote add |
添加远程仓库的命令 |
origin |
远程仓库的默认别名(习惯命名,可自定义) |
| URL | 远程仓库的地址 |
② 查看关联的远程仓库:
bash
$ git remote -v
origin https://github.com/yourusername/myproject.git (fetch)
origin https://github.com/yourusername/myproject.git (push)
③ 推送到远程仓库:
bash
$ git push -u origin master
| 参数 | 含义 |
|---|---|
push |
推送本地提交到远程 |
-u |
设置上游分支(--set-upstream 的缩写),以后可以直接 git push |
origin |
推送到哪个远程仓库 |
master |
推送哪个分支 |
第一次推送时,你需要输入 GitHub/Gitee 的用户名和密码(或 Personal Access Token)。
💡 推送成功后,刷新 GitHub 页面就能看到你的代码了!后续如果配置了 SSH 密钥,就可以免密码推送。
七、Git 常用命令详解
除了上面介绍的基本命令外,Git 还有很多非常有用的命令。下面逐一详细讲解。
7.1 查看仓库状态 ------ git status
bash
$ 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.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
newfile.py
no changes added to commit (use "git add" and/or "git commit")
这个命令告诉你:
- 当前在哪个分支
- 哪些文件被修改了但还没有添加到暂存区(红色)
- 哪些文件已经添加到暂存区但还没有提交(绿色)
- 是否有未跟踪的新文件
常用变体:
bash
git status -s # 精简输出(短格式)
精简格式的状态标识:
| 标记 | 含义 |
|---|---|
M |
工作区修改了,未暂存(M 在右边=工作区,左边=暂存区) |
M |
已暂存的修改 |
?? |
未跟踪的新文件 |
A |
新文件已暂存 |
D |
删除已暂存 |
R |
重命名已暂存 |
7.2 查看提交历史 ------ git log
bash
$ git log
commit a5a8f007f4c8e39d8cfc1d0c5c7fe8a8b3e6d9f2 (HEAD -> master)
Author: Your Name <your.email@example.com>
Date: Mon Jan 1 10:00:00 2024 +0800
Initial commit
各字段含义:
| 字段 | 说明 |
|---|---|
commit xxxxx |
完整的 SHA-1 哈希值 |
(HEAD -> master) |
HEAD 指针当前位置和所在分支 |
Author: |
提交者信息 |
Date: |
提交时间 |
| (空行下方) | 提交信息 |
git log 的强大选项:
| 命令 | 效果 |
|---|---|
git log --oneline |
每个提交只显示一行(哈希前7位 + 信息) |
git log --oneline --graph |
图形化显示分支合并历史(非常实用!) |
git log --author="name" |
只看某人的提交 |
git log --since="2024-01-01" |
只看某日期之后的提交 |
git log --until="2024-12-31" |
只看某日期之前的提交 |
git log -n 5 |
只看最近 5 条 |
git log --stat |
显示每次提交的文件变更统计 |
git log -p |
显示每次提交的具体 diff 内容 |
图形化展示(强烈推荐):
bash
$ git log --oneline --graph --all
* c4b3d2f (HEAD -> main) Merge branch 'feature'
|\
| * e5f6g7h (feature) Add new login page
* | a8b9c0d Fix navigation bug
|/
* d1e2f3g Initial commit
7.3 克隆远程仓库 ------ git clone
bash
$ git clone https://github.com/yourusername/myproject.git
Cloning into 'myproject'...
remote: Enumerating objects: 12, done.
remote: Counting objects: 100% (12/12), done.
...
作用: 将远程仓库完整地克隆到本地,包括所有历史记录和分支。
克隆完成后,你会得到一个包含以下内容的本地仓库:
- 所有源代码文件
- 完整的提交历史
- 所有分支
- 自动关联的远程仓库(默认别名为
origin)
7.4 从远程仓库拉取代码 ------ git pull
bash
$ git pull
作用: 从远程仓库拉取最新的代码,并自动合并到当前分支。
💡
git pull=git fetch+git merge两步操作的组合。先获取远程更新,再自动合并到当前分支。
7.5 查看文件修改内容 ------ git diff
bash
# 查看工作区中尚未暂存的修改(对比工作区 vs 暂存区)
$ git diff
# 查看已暂存但尚未提交的修改(对比暂存区 vs 最新提交)
$ git diff --cached
# 或
$ git diff --staged
# 查看某两个提交之间的差异
$ git diff commit1 commit2
# 查看两个分支之间的差异
$ git diff main feature
diff 输出的格式解读:
diff
diff --git a/README.md b/README.md
index abc1234..def5678 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
# My Project
+This is a new line.
+
Hello World!
| 符号 | 含义 |
|---|---|
--- a/file |
旧版本(删除的部分) |
+++ b/file |
新版本(增加的部分) |
-红色行 |
被删除的内容 |
+绿色行 |
新增的内容 |
@@ -1,3 +1,5 @@ |
变更位置:旧文件第1-3行 → 新文件第1-5行 |
7.6 撤销修改 ------ Git 的"后悔药"
Git 提供了多层撤销机制,针对不同的场景有不同的命令:
场景 1:工作区修改了,想丢弃(未执行 git add)
bash
$ git checkout -- <文件名>
# 或者(Git 2.23+ 推荐的新语法)
$ git restore <文件名>
效果: 将文件恢复到最近一次 git commit 或 git add 时的状态。⚠️ 不可恢复!
场景 2:已经 git add 了,想撤出暂存区
bash
$ git reset HEAD <文件名>
# 或者(Git 2.23+ 推荐的新语法)
$ git restore --staged <文件名>
效果: 将文件从暂存区移回工作区,但保留文件的修改内容。只是取消了"暂存"这个动作。
场景 3:已经 git commit 了,想撤销这次提交
bash
# 方式一:撤销提交,保留修改在工作区
$ git reset --soft HEAD~1
# 方式二:撤销提交,保留修改在暂存区
$ git reset HEAD~1
# 方式三:彻底撤销提交(慎用!修改会丢失)
$ git reset --hard HEAD~1
| 参数 | 效果 |
|---|---|
--soft |
回退到 git add 之后、git commit 之前的状态 |
| (默认) | 回退到 git add 之前的状态(修改保留在工作区) |
--hard |
彻底回退,所有修改全部丢失 |
⚠️
git reset --hard是危险操作!执行前请确保你已经备份了重要的修改。
7.7 删除文件 ------ git rm
bash
# 删除文件并暂存(相当于 rm + git add 两步合一)
$ git rm <文件名>
$ git commit -m "Delete file"
# 只从 Git 仓库中移除跟踪,保留本地文件
$ git rm --cached <文件名>
$ git commit -m "Remove from tracking"
💡
git rm --cached常用于不小心把不该跟踪的文件(如.env、密码文件)提交到了 Git 的情况。
7.8 重命名文件 ------ git mv
bash
$ git mv <旧文件名> <新文件名>
$ git commit -m "Rename file"
等效于以下三步操作:
mv old new------ 重命名文件git rm old------ 从 Git 中删除旧文件git add new------ 将新文件添加到 Git
八、远程仓库操作详解
8.1 查看远程仓库
bash
$ git remote -v
origin https://github.com/user/repo.git (fetch)
origin https://github.com/user/repo.git (push)
fetch表示从此地址拉取数据push表示向此地址推送数据
8.2 添加远程仓库
bash
git remote add <别名> <URL>
示例:
bash
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git
💡 通常
origin指向你自己的 fork,upstream指向原始仓库(参与开源项目时常这么配)。
8.3 删除远程仓库关联
bash
git remote remove <别名>
# 例如
git remote remove origin
8.4 重命名远程仓库
bash
git remote rename <旧名> <新名>
# 例如
git remote rename origin myorigin
8.5 获取远程更新但不合并 ------ git fetch
bash
$ git fetch origin
与 git pull 的区别:
| 命令 | 行为 |
|---|---|
git fetch |
只下载远程数据到本地,不自动合并。你可以检查后再决定是否合并 |
git pull |
下载 + 自动合并到当前分支 |
💡 在重要协作场景中,推荐先用
git fetch查看远程有什么更新,确认无误后再git merge合并。更安全可控。
九、冲突解决 ------ 团队协作必经之路
在团队协作中,当多个开发者同时修改同一个文件的同一部分时,就会发生冲突(Conflict)。Git 无法自动解决这种冲突,需要开发者手动处理。
9.1 冲突是如何发生的?
时间线:
────────────────────────────────────────────────▶
开发者A: 修改了 README.md 第10行 → 提交 → push ✓
开发者B: 也修改了 README.md 第10行 → 提交 → push ✗ CONFLICT!
↓
必须先 pull(此时产生冲突)
9.2 冲突发生时的现象
当你执行 git pull 或 git merge 时,如果发生冲突,Git 会显示类似以下的输出:
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
9.3 冲突标记详解
Git 会在冲突的文件中插入特殊的标记来标识冲突的部分:
markdown
<<<<<<< HEAD
这是本地分支(当前分支)修改的内容
=======
这是远程分支(incoming branch)修改的内容
>>>>>>> feature/login
标记符号的含义:
| 符号 | 含义 |
|---|---|
<<<<<<< HEAD |
冲突开始标记,HEAD 表示当前所在的分支 |
======= |
分隔线,上方是当前分支的内容,下方是要合并的分支的内容 |
>>>>>>> feature/login |
冲突结束标记,后面是要合并的分支名 |
9.4 解决冲突的步骤
第一步:打开冲突文件,手动编辑
删除 Git 插入的特殊标记(<<<<<<<、=======、>>>>>>>),决定最终保留哪些内容。你可以:
- 只保留当前分支的版本
- 只保留远程分支的版本
- 合并两个版本的修改(最常见的情况)
第二步:标记为已解决
bash
$ git add README.md
💡 注意:解决冲突后用的是
git add(不是git commit)。git add在这里的意思是"冲突已解决,请把这个文件标记为 resolved"。
第三步:完成合并提交
bash
$ git commit -m "Resolve merge conflict in README.md"
⚠️ 很多 IDE(VS Code、IntelliJ 等)都提供了可视化的冲突解决工具,可以图形化地选择保留哪一侧的内容,比手动编辑更高效。
十、.gitignore 文件 ------ 告诉 Git 忽略什么
在项目中,有些文件是不应该被 Git 跟踪的。.gitignore 文件就是用来告诉 Git:"这些文件请不要管它们!"
10.1 常见需要忽略的文件类型
| 类型 | 示例 |
|---|---|
| 编译产物 | .o、.obj、.class、.exe |
| 依赖目录 | node_modules/、vendor/、venv/ |
| IDE 配置 | .idea/、.vscode/、*.swp、*.swo |
| 日志文件 | *.log |
| 临时文件 | *.tmp、*.temp、.DS_Store |
| 敏感信息 | .env、*.key、passwords.txt |
| 构建输出 | dist/、build/、bin/、out/ |
10.2 .gitignore 语法规则
# 以 # 开头的是注释行
# 匹配所有 .o 结尾的文件
*.o
*.obj
# 匹配所有 .exe 可执行文件
*.exe
# 匹配所有日志文件
*.log
# 匹配 VSCode 配置目录(/ 结尾表示目录)
.vscode/
# ! 表示"不忽略"(排除例外)
!important.log
# 匹配 lib 目录下的所有内容
lib/
# ** 匹配任意层级的目录
docs/**/*.tmp
# 前缀 / 表示只匹配项目根目录
/config.yml
语法速查表:
| 语法 | 含义 | 示例 |
|---|---|---|
# |
注释 | # 这是注释 |
* |
匹配任意数量的字符(不含 /) |
*.log |
? |
匹配单个字符 | file?.txt |
/ |
目录标记或路径锚定 | dir/ |
** |
匹配任意层级目录 | src/**/*.js |
! |
否定(不忽略) | !important.log |
10.3 一个典型的 C/C++ 项目 .gitignore
gitignore
# 编译产物
*.o
*.obj
*.exe
*.out
*.dll
*.so
*.dylib
# 调试信息
*.dSYM/
*.su
*.idb
*.pdb
# IDE 和编辑器
.vscode/
.idea/
*.swp
*.swo
*~
# 依赖目录
__pycache__/
node_modules/
vendor/
venv/
build/
cmake-build-debug/
# 日志和临时文件
*.log
*.tmp
*.temp
.DS_Store
Thumbs.db
# 敏感信息(绝对不能提交!!)
.env
*.pem
*.key
secrets.config
⚠️ 如果你不小心把不该提交的文件(如密码文件)提交到了 Git,使用
git rm --cached <文件>把它从跟踪中移除,然后把文件名加到.gitignore中。
十一、GitHub 完整工作流
前面讲了各种命令,现在把它们串联起来,形成一个完整的 GitHub 工作流。
11.1 首次使用的完整流程
① 注册 GitHub 账号(需要邮箱验证)
↓
② 在 GitHub 上创建 New Repository
↓
③ 本地克隆(或初始化后关联)
$ git clone https://github.com/user/repo.git
$ cd repo
↓
④ 编写/修改代码
↓
⑤ git add .
↓
⑥ git commit -m "描述你的改动"
↓
⑦ git push -u origin main
(首次需输入用户名密码/Token)
↓
⑧ 刷新 GitHub 页面查看代码 ✓
11.2 日常开发循环
修改代码 → git add → git commit → git push
↑ │
└──────────────────────────────────┘
每天重复这个循环
11.3 团队协作循环
① 开始工作前先拉取最新代码
$ git pull origin main
↓
② 创建功能分支(可选但推荐)
$ git checkout -b feature/new-feature
↓
③ 开发、测试、提交
$ git add .
$ git commit -m "Add new feature"
↓
④ 推送功能分支到远程
$ git push origin feature/new-feature
↓
⑤ 在 GitHub 上创建 Pull Request (PR)
↓
⑥ Code Review 通过后合并到主线
↓
⑦ 删除功能分支,回到主线继续开发
$ git checkout main
$ git pull origin main
$ git branch -d feature/new-feature
十二、🤔 几个思考题
学完本文,来试试回答这些问题:
1️⃣ Git 和 SVN 的本质区别是什么?
答: Git 是分布式版本控制系统,每个开发者本地都有一个完整的仓库(包含全部历史记录);SVN 是集中式版本控制系统,只有一个中央服务器保存完整数据。这带来的核心区别是:
- Git 支持离线工作(大部分操作在本地完成)
- Git 的分支操作几乎零成本(只是创建指针)
- Git 更安全(每个本地仓库都是完整备份)
- SVN 的 centralized 模式在网络断开时基本瘫痪
💡 用一句话总结:SVN 是"一台服务器大家连",Git 是"每人一台完整服务器再互相同步"。
2️⃣ git add、git commit、git push 分别操作的是哪个区域?
答:
git add:工作区 → 暂存区(把修改放入待提交列表)git commit:暂存区 → 本地仓库(把暂存的内容永久记录)git push:本地仓库 → 远程仓库(把本地记录同步到服务器)
三者依次执行,构成了 Git 的核心工作流。
3️⃣ git fetch 和 git pull 有什么区别?什么时候该用哪个?
答: git fetch 只是从远程下载最新数据到本地仓库,不会自动合并到你当前的分支;git pull = git fetch + git merge,下载后会立即尝试自动合并。
- 想先看看远程改了什么 → 用
git fetch - 确认没问题想直接更新 → 用
git pull - 重要项目推荐始终用
fetch+ 手动merge,更安全可控
4️⃣ 什么时候会产生冲突?如何避免?
答: 当多人同时修改同一个文件的同一部分,并且 Git 无法自动判断该保留哪个版本时,就会产生冲突。
减少冲突的方法:
- 保持频繁同步(每天开始工作前先
git pull) - 功能模块化,不同人改不同文件
- 使用功能分支,减小合并范围
- 保持提交粒度小而清晰
- 代码 Review 文化(PR/MR 流程)
5️⃣ .gitignore 文件应该放在哪里?什么时候创建最好?
答: .gitignore 应该放在项目的根目录,并且越早创建越好------理想情况下是在 git init 之后立刻创建。因为一旦敏感文件或不该跟踪的文件被提交到了 Git 历史中,即使后来加入 .gitignore,那些文件仍然存在于历史记录中(需要额外的清理操作才能彻底移除)。
总结
让我们回顾一下本文的核心知识点:
┌─────────────────────────────────────────────────────────┐
│ Git 知识体系总览 │
├─────────────────────────────────────────────────────────┤
│ │
│ 📖 基础概念 │
│ ├── 三个区域:工作区 → 暂存区 → 本地仓库 → 远程仓库 │
│ ├── 四种状态:Untracked / Unmodified / Modified / Staged│
│ ├── 分支 = 指针(不是拷贝!) │
│ └── 提交 = 快照(含哈希、作者、时间、父指针) │
│ │
│ 🔧 核心命令(三板斧) │
│ ├── git add → 工作区 → 暂存区 │
│ ├── git commit → 暂存区 → 本地仓库 │
│ └── git push → 本地仓库 → 远程仓库 │
│ │
│ 🛠️ 常用命令 │
│ ├── git status / log / diff → 查看状态和历史 │
│ ├── git clone / pull / fetch → 远程交互 │
│ ├── git reset / restore / checkout → 撤销修改 │
│ ├── git rm / mv → 删除和重命名 │
│ └── git remote → 远程仓库管理 │
│ │
│ ⚔️ 进阶技能 │
│ ├── 冲突解决(<<<<<<< / ======= / >>>>>>> 标记) │
│ ├── .gitignore 规则(* ? ! ** / 语法) │
│ └── 分支管理与团队协作工作流 │
│ │
│ 🎯 Git 的五大优势 │
│ ├── 1. 完全分布式架构 │
│ ├── 2. 惊人的速度 │
│ ├── 3. 强大的分支管理 │
│ ├── 4. 数据完整性(SHA-1 哈希) │
│ └── 5. 增量存储(节省空间) │
│ │
└─────────────────────────────────────────────────────────┘
Git 是一个功能强大、灵活高效的分布式版本控制系统,它已经成为现代软件开发的标准工具。通过本文的学习,你应该已经掌握了:
✅ Git 的设计理念和核心优势
✅ 三个工作区域和四种文件状态
✅ 从安装配置到日常开发的完整工作流
✅ 每个核心命令的详细用法和参数
✅ 冲突解决和团队协作的实用技巧
当然,Git 的功能远不止于此。还有更多高级特性等你探索:
- 🌿 进阶分支策略(Git Flow、GitHub Flow)
- 🔄 变基(rebase) vs 合并(merge)
- 📦 子模块(submodule) 和 子树(subtree)
- 🏷️ 标签(tag) 管理
- 🔍 交互式暂存 和 cherry-pick
💡 记住:学习 Git 最好的方法就是多实践。从今天开始,在你的每个项目中都使用 Git 来管理代码,遇到问题就查就试,你会发现它给你的开发工作带来巨大的便利和安全感。
✅ 本节完...
📝 作者:say-fall | 编辑:say-fall | 🌟 原创不易,如果对你有帮助,记得 👍 点赞 + ⭐ 收藏 哦!