Git 教程:从零开始,轻松管理你的代码 – wiki基地


Git 教程:从零开始,轻松管理你的代码

在现代软件开发的浩瀚海洋中,代码是我们的船只,而版本控制系统(VCS)则是确保这艘船在风浪中稳健航行、不迷失方向的罗盘与舵手。无论是个人项目还是团队协作,一套高效的代码管理机制都是不可或缺的。在这其中,Git 无疑是最广为人知、功能最强大且应用最广泛的版本控制系统。

本文将带领你踏上 Git 的学习之旅,从最基础的概念到实际操作,乃至一些进阶技巧,让你能够从零开始,轻松驾驭 Git,告别手动备份和“最终版-最终版2-最终版真的最终版.zip”的混乱噩梦,真正实现代码的有序管理与高效协作。


第一章:初识版本控制与Git

1.1 什么是版本控制?为什么要用它?

想象一下,你正在写一篇重要的论文或开发一个复杂的软件。你不断地修改、完善、添加新功能。如果没有版本控制,你可能会遇到以下问题:

  • 历史追溯困难: 想要回到上周的代码状态?几乎不可能,除非你手动备份了每个版本。
  • 团队协作混乱: 多人同时修改同一个文件,如何合并彼此的修改?谁覆盖了谁的成果?
  • 错误恢复艰难: 不小心引入了一个重大 Bug,或者删除了关键代码,如何快速回滚到之前的稳定版本?
  • 项目迭代失控: 无法清晰地知道每个功能是在哪个版本添加的,谁添加的,为了解决什么问题。

版本控制系统(Version Control System, VCS)正是为了解决这些问题而生。它能够:

  1. 追踪所有变更: 记录项目文件每一次的修改、谁修改的、修改了什么、修改的原因。
  2. 版本回溯与恢复: 随时可以回到项目的任意历史版本,或者撤销不想要的修改。
  3. 支持团队协作: 允许多人并行开发,并提供机制来合并不同成员的代码修改。
  4. 分支管理: 提供独立的工作线,方便进行实验性开发、新功能开发,而不会影响主线的稳定性。

简而言之,版本控制就是代码的“时间机器”和“协作大脑”。

1.2 Git:分布式版本控制的王者

在版本控制系统的发展历程中,大致经历了以下阶段:

  • 本地版本控制系统 (Local VCS): 例如 RCS,只在本地记录文件的历史版本。
  • 集中式版本控制系统 (Centralized VCS, CVCS): 例如 SVN、CVS。所有版本历史都存储在中央服务器上。开发者从中央服务器获取最新代码,提交修改也到中央服务器。优点是集中管理,但缺点是单点故障(服务器宕机则无法工作),且离线状态下无法进行版本控制操作。
  • 分布式版本控制系统 (Distributed VCS, DVCS): 例如 Git、Mercurial。每个开发者都拥有一个完整的项目仓库副本,包含所有历史版本。这意味着你可以在本地进行大部分版本控制操作,即使没有网络也能工作。当你需要与他人协作时,才与远程仓库进行同步。

Git 的诞生: Git 由 Linux 内核的创造者 Linus Torvalds 于 2005 年开发。由于对现有 CVCS(尤其是 BitKeeper)的不满,他仅用两周时间就创造了 Git。它的设计目标是:速度快、简单的设计、对非线性开发(数千个并行分支)的强力支持、完全分布式以及能有效处理大型项目(如 Linux 内核)。

Git 的核心优势:

  • 完全分布式: 每个人都有完整的项目历史,无需依赖中央服务器即可工作。
  • 超快速度: 多数操作都在本地完成,响应速度极快。
  • 强大的分支与合并能力: Git 的分支模型非常轻量且高效,使得分支创建、切换和合并成为日常操作。
  • 数据完整性: Git 对所有数据使用 SHA-1 校验和,确保版本历史的不可篡改性。

理解了版本控制的重要性以及 Git 的核心优势后,我们就可以正式开始 Git 的学习了。


第二章:搭建你的Git环境

在开始使用 Git 之前,你需要先在你的电脑上安装它。

2.1 安装 Git

a) Windows 系统:

前往 Git 官方网站 (https://git-scm.com/download/win) 下载最新版的 Git for Windows 安装程序。

安装过程通常是傻瓜式的“下一步”,但在某些选项上,你可以根据自己的习惯选择:

  • 选择默认编辑器: 可以选择你熟悉的编辑器,如 VS Code、Notepad++ 或 Vim。如果不知道选哪个,默认的 Vim 也可以。
  • 调整 PATH 环境: 建议选择 “Git from the command line and also from 3rd-party software”,这样你可以在任何命令行工具中使用 Git 命令。
  • 选择 HTTPS 传输后端: 默认的 “Use the OpenSSL library” 即可。
  • 配置行末换行符转换: 建议选择 “Checkout Windows-style, commit Unix-style line endings”。这有助于避免跨平台协作时的换行符问题。

安装完成后,你会在开始菜单中找到 “Git Bash”。这是一个模拟 Linux 环境的命令行工具,我们将主要在这里执行 Git 命令。

b) macOS 系统:

macOS 用户有几种安装方式:

  • Xcode Command Line Tools (推荐): 如果你安装了 Xcode,Git 已经包含在其中。如果没有,在终端输入 git --version,系统会提示你安装 Command Line Tools,按照提示安装即可。
  • Homebrew (包管理器): 如果你安装了 Homebrew(macOS 上流行的包管理器),可以直接在终端输入 brew install git 来安装。
  • Git 官方安装程序: 同样可以前往 Git 官网下载 macOS 版本的安装程序。

c) Linux 系统:

大多数 Linux 发行版都可以通过其包管理器安装 Git。

  • Debian/Ubuntu: sudo apt update && sudo apt install git
  • Fedora: sudo dnf install git
  • CentOS/RHEL: sudo yum install git (较旧版本) 或 sudo dnf install git (较新版本)

2.2 配置 Git

安装完成后,你需要进行一些初始配置,告诉 Git 你的身份信息。这些信息将作为每次提交(commit)的作者信息,非常重要。

在 Git Bash (Windows) 或终端 (macOS/Linux) 中输入以下命令:

bash
git config --global user.name "你的名字"
git config --global user.email "你的邮箱@example.com"

  • --global 参数表示这些配置是全局性的,适用于你在此计算机上的所有 Git 仓库。如果你想为某个特定项目使用不同的名字或邮箱,可以在该项目目录下不带 --global 参数地执行 git config 命令。
  • user.nameuser.email 是你的提交记录中会显示的信息。请务必填写真实信息。

你可以通过以下命令检查你的配置:

bash
git config --list

你也可以查看某个特定配置:

bash
git config user.name

至此,你的 Git 环境已经搭建完毕,可以开始实际操作了!


第三章:Git的核心操作:本地仓库管理

Git 的强大之处在于它对“仓库”(Repository)的管理。一个 Git 仓库包含了项目的所有文件和完整的历史版本信息。

3.1 工作区、暂存区、版本库:Git 的三大区域

在深入学习 Git 命令之前,理解 Git 的三个主要区域至关重要:

  1. 工作区 (Working Directory): 就是你在电脑上能看到的、包含 .git 目录以外的项目文件和目录。这是你进行日常开发,编辑代码的地方。
  2. 暂存区 (Staging Area / Index): 这是一个轻量级的缓存区域。当你对工作区的文件进行修改后,需要先将这些修改“添加”到暂存区,然后才能提交到版本库。暂存区允许你选择性地提交文件的一部分修改。
  3. 版本库 (Repository): 也称为 Git 仓库。这是 Git 存储项目所有历史版本数据的地方,通常是一个名为 .git 的隐藏目录。当你执行 git commit 命令时,暂存区的所有内容就会被永久性地保存到版本库中,形成一个新的版本。

这三者的关系可以简单理解为:你在工作区修改文件 -> 将你想要提交的修改添加到暂存区 (git add) -> 将暂存区的修改提交到版本库 (git commit)。

3.2 初始化一个新的 Git 仓库

要开始使用 Git 管理一个项目,你需要在这个项目的根目录下初始化一个 Git 仓库。

a) 初始化新项目:

进入你想要进行版本控制的空目录或现有项目目录:

bash
cd /path/to/your/project
git init

执行 git init 后,Git 会在当前目录下创建一个名为 .git 的隐藏目录。这个目录就是 Git 仓库,所有版本控制信息都存储在这里。

b) 克隆现有仓库:

如果你想参与一个已有的 Git 项目,通常是从远程仓库(如 GitHub)克隆一份到本地:

bash
git clone <repository_url>

例如:git clone https://github.com/octocat/Spoon-Knife.git

git clone 会自动完成两件事:
1. 创建一个名为 Spoon-Knife 的目录(如果URL的结尾是.git,则会去除.git作为目录名)。
2. 在这个目录中初始化一个 Git 仓库,并下载远程仓库的所有历史版本。

3.3 将文件添加到暂存区 (git add)

在工作区创建或修改文件后,你需要使用 git add 命令将这些变更添加到暂存区。

  • 添加单个文件:
    bash
    git add README.md
  • 添加多个文件:
    bash
    git add index.html style.css script.js
  • 添加某个目录下的所有文件:
    bash
    git add src/
  • 添加当前目录下所有变更(包括新建、修改、删除):
    bash
    git add .

    注意: git add . 会添加所有未被 .gitignore 忽略的变更,包括新建文件、修改文件和被标记为删除的文件。

3.4 提交更改到版本库 (git commit)

当暂存区的内容准备好后,你就可以将其提交到版本库,创建一个新的版本快照。每次提交都需要附带一条有意义的提交信息(commit message)。

bash
git commit -m "你的提交信息"

例如:
bash
git commit -m "feat: implement user login functionality"

提交信息的最佳实践:
* 简洁明了的主题行: 第一行是提交的主题,通常不超过 50-72 个字符。
* 空一行: 主题行和正文之间留一个空行。
* 详细正文(可选): 描述本次提交的详细内容、原因、解决了什么问题、引入了什么新功能。

一个好的提交信息能够帮助你和团队成员快速理解每个版本的变更内容,方便日后追溯和维护。

3.5 查看仓库状态 (git status)

git status 是一个非常常用的命令,它会显示工作区和暂存区的当前状态,帮助你了解哪些文件被修改了、哪些文件在暂存区等待提交。

bash
git status

可能的状态信息:

  • On branch master / On branch main 表示你当前所在的分支。
  • nothing to commit, working tree clean 工作区和暂存区都没有未提交的修改,一切干净。
  • Untracked files: 新创建的文件,Git 还没有开始追踪它们。需要 git add 来添加到暂存区。
  • Changes not staged for commit: 工作区中已修改但尚未添加到暂存区的文件。
  • Changes to be committed: 已经添加到暂存区,等待提交的文件。

3.6 查看提交历史 (git log)

git log 命令可以查看项目的提交历史,了解每次提交的详细信息。

bash
git log

git log 会显示:

  • 每次提交的 SHA-1 校验和(commit ID)。
  • 作者信息(Author)。
  • 提交日期(Date)。
  • 提交信息(Commit Message)。

常用的 git log 参数:

  • git log --oneline:以一行显示每个提交,只显示 commit ID 的前几位和提交信息。
  • git log --graph:以图形化的方式显示分支合并历史。
  • git log --oneline --graph --all:结合了上述所有功能,并显示所有分支的历史。
  • git log -p:显示每次提交的具体修改内容(diff)。
  • git log --author="你的名字":按作者过滤。
  • git log --since="2 weeks ago":查看两周内的提交。

3.7 查看文件差异 (git diff)

git diff 命令用于比较不同状态下的文件差异。

  • 查看工作区与暂存区的差异: (你改了什么但还没 git add
    bash
    git diff
  • 查看暂存区与最新提交的差异: (你 git add 了什么但还没 git commit
    bash
    git diff --staged
    # 或 git diff --cached
  • 查看工作区与最新提交的差异: (你改了什么,包括已 add 和未 add 的,与上次提交做比较)
    bash
    git diff HEAD
  • 比较两个提交之间的差异:
    bash
    git diff <commit_id_1> <commit_id_2>

3.8 撤销操作

Git 提供了多种撤销操作,让你能够灵活地处理不小心犯下的错误。

  • 撤销工作区的修改 (git restore):
    如果你对文件进行了修改,但还没 git add,想放弃这些修改,回到上次提交或暂存时的状态:
    bash
    git restore <file_name>
    # 示例:git restore index.html
    # 放弃所有工作区修改:git restore .
  • 将文件从暂存区中取消暂存 (git restore --staged):
    如果你已经 git add 了一个文件,但又不想提交它了,想把它从暂存区移回工作区(保留修改):
    bash
    git restore --staged <file_name>
    # 示例:git restore --staged index.html
  • 修改最近一次提交 (git commit --amend):
    如果你刚提交了一次,但发现提交信息写错了,或者漏掉了一个小文件没有 git add

    1. 如果只是修改提交信息:git commit --amend -m "新的提交信息"
    2. 如果漏掉文件:先 git add 漏掉的文件,然后 git commit --amend --no-edit ( --no-edit 表示沿用上次的提交信息,你也可以不加它,直接编辑提交信息)
      注意: git commit --amend 会用一个新的提交替换掉旧的提交,改变提交的 SHA-1 ID。因此,不要对已经推送到远程仓库的提交使用 amend,这会给团队协作带来麻烦。
  • 回滚到某个历史版本 (git reset):
    git reset 是一个强大的命令,可以移动 HEAD 指针和/或暂存区。它有三个主要模式:

    • git reset --soft <commit_id>

      • HEAD 指针移动到指定的 <commit_id>
      • 工作区保持不变。
      • 暂存区会包含 <commit_id> 到当前 HEAD 之间的所有变更。
      • 适用于:你想回退到某个版本,但保留所有变更,准备重新提交。
    • git reset --mixed <commit_id> (默认模式):

      • HEAD 指针移动到指定的 <commit_id>
      • 暂存区与 <commit_id> 完全一致(即清空暂存区)。
      • 工作区保持不变。
      • 适用于:你想回退到某个版本,并清空暂存区,所有变更都回到工作区,准备重新组织提交。
    • git reset --hard <commit_id>

      • HEAD 指针移动到指定的 <commit_id>
      • 暂存区与 <commit_id> 完全一致。
      • 工作区也会回滚到 <commit_id> 的状态,这意味着 <commit_id> 之后的所有未提交的修改都会被永久删除!
      • 适用于:你确定要彻底放弃 <commit_id> 之后的所有更改,回到一个干净的历史版本。这是一个危险的命令,请谨慎使用!

    示例:
    bash
    git log --oneline # 找到你想要回滚到的 commit ID
    git reset --hard HEAD~1 # 回退到上一个版本 (HEAD~1 表示 HEAD 的上一个版本)
    git reset --hard <commit_id> # 回退到指定的 commit ID

    注意: git reset 同样会改写历史。不要对已经推送到远程仓库的提交使用 reset --hard,除非你明确知道你在做什么,并且已经通知了团队。


第四章:强大的分支与合并策略

分支(Branch)是 Git 最强大的特性之一,它让并行开发和实验性开发变得简单高效。

4.1 什么是分支?为什么要用它?

想象一下,你的项目有一个稳定的 main(或 master)分支,它代表了随时可发布的代码。现在你需要开发一个新功能。如果你直接在 main 上开发,可能会:

  • 影响主线稳定性: 新功能可能需要很长时间才能完成,期间 main 分支的代码可能处于不稳定状态。
  • 阻塞其他开发: 其他团队成员如果需要基于 main 开发,就会受到你的影响。
  • 回滚困难: 如果新功能开发失败,想放弃所有改动,就需要回滚整个 main 分支。

分支就是解决这些问题的利器。它就像从主线分叉出去的一条独立开发路径。你可以在自己的分支上随意开发、修改、提交,而不会影响到 main 分支。当新功能开发完成并测试通过后,再将你的分支合并回 main

Git 的分支非常轻量级,它仅仅是一个指向某个 commit 的指针。所以创建和切换分支的速度非常快。

4.2 分支的基本操作

  • 查看所有分支:
    bash
    git branch

    当前分支会用 * 标记。

  • 创建新分支:
    bash
    git branch <new_branch_name>
    # 例如:git branch feature/user-profile

    这只是创建了一个新分支,你仍然停留在当前分支。

  • 切换分支:
    bash
    git checkout <branch_name>
    # 例如:git checkout feature/user-profile

    切换分支会改变你的工作区,使其反映出目标分支的最新提交内容。

  • 创建并切换到新分支(常用):
    bash
    git checkout -b <new_branch_name>
    # 例如:git checkout -b bugfix/login-issue

    这相当于 git branch <new_branch_name>git checkout <new_branch_name> 的组合。

  • 删除分支:
    当一个分支的功能开发完毕并合并到主线后,通常可以删除它。
    bash
    git branch -d <branch_name>
    # 例如:git branch -d feature/user-profile

    -d 参数只能删除已合并的分支。如果分支尚未合并但你确定要删除(会丢失未合并的提交),可以使用 -D 参数(强制删除):
    bash
    git branch -D <branch_name>

4.3 合并分支 (git merge)

当你在一个功能分支上完成了开发,并希望将其集成回主线(例如 main 分支)时,就需要进行合并。

  1. 切换到目标分支: 首先,切换到你想要合并到的目标分支(通常是 mainmaster)。
    bash
    git checkout main
  2. 执行合并操作: 然后,将你的功能分支合并到当前分支。
    bash
    git merge <feature_branch_name>
    # 例如:git merge feature/user-profile

Git 合并的两种常见情况:

  • Fast-forward (快进合并): 如果目标分支(例如 main)在你创建功能分支后没有发生新的提交,那么 Git 会直接将 main 指针移动到功能分支的最新提交上,合并过程非常简单。
    A -- B -- C (main, feature)
    合并后:
    A -- B -- C (main, feature)
    main 直接“快进”到了 C

  • Recursive (三方合并): 如果目标分支在你开发功能分支期间也有新的提交,Git 会尝试进行一个三方合并。它会找到两个分支的共同祖先(base),然后将两个分支的修改合并到一起,并创建一个新的合并提交(merge commit)。
    D -- E (feature)
    /
    A -- B -- C (main)

    合并后:
    D -- E
    / \
    A -- B -- C -- F (main)
    /
    (feature)

    F 就是新的合并提交。

4.4 合并冲突(Merge Conflicts)

合并时最常见的问题就是冲突。当两个分支在同一个文件的同一行代码,或不同文件但紧密关联的区域进行了不同的修改,Git 无法自动判断应该保留哪个修改,就会发生合并冲突。

如何解决冲突:

  1. Git 会暂停合并: 当发生冲突时,git merge 命令会提示你冲突信息,并告诉你哪些文件发生了冲突。
    Auto-merging <file_name>
    CONFLICT (content): Merge conflict in <file_name>
    Automatic merge failed; fix conflicts and then commit the result.
  2. 查看状态: git status 会显示冲突的文件,它们会处于 unmerged 状态。
  3. 手动解决冲突: 打开冲突的文件,你会看到类似这样的标记:
    <<<<<<< HEAD
    console.log("This is the main branch version.");
    =======
    console.log("This is the feature branch version, more awesome!");
    >>>>>>> feature/new-feature

    • <<<<<<< HEAD======= 之间是当前分支(HEAD 所指向的分支,即 main)的修改。
    • =======>>>>>>> feature/new-feature 之间是被合并分支(feature/new-feature)的修改。

    你需要手动编辑文件,删除这些标记,并保留你想要的或合并后的代码。例如,你可以选择保留其中一个,或者融合两者的内容:
    javascript
    console.log("This is the combined and resolved version.");

    4. 将解决后的文件添加到暂存区:
    bash
    git add <conflicted_file_name>

    当你解决完所有冲突文件并 git add 它们之后,git status 会显示它们处于 Changes to be committed 状态。
    5. 提交合并结果:
    bash
    git commit -m "Merge branch 'feature/new-feature' into main"

    Git 会自动为你生成一个默认的合并提交信息,你可以直接使用或修改。

解决冲突是 Git 日常工作中非常重要的一部分,需要多加练习。


第五章:协作开发:远程仓库的魔力

到目前为止,我们所有的操作都在本地完成。要与团队成员协作,或者备份你的代码,就需要用到远程仓库。GitHub、GitLab、Bitbucket 是最流行的远程仓库托管服务。

5.1 什么是远程仓库?

远程仓库是你的 Git 仓库在网络上的一个副本。它可以存储你的代码,并作为团队成员之间交换代码的中心点。当你的本地仓库与远程仓库连接后,你可以:

  • 推送到远程: 将你本地的提交上传到远程仓库。
  • 从远程拉取: 将远程仓库的最新提交下载到本地。

5.2 克隆远程仓库 (git clone)

如果你要参与一个已有的远程项目,最常见的方式是克隆该仓库到本地。

“`bash
git clone

例如:git clone https://github.com/your-username/your-project.git

``
这会在当前目录下创建一个与远程仓库同名的文件夹,并初始化一个本地 Git 仓库,拉取所有历史记录,并自动设置一个名为
origin` 的远程别名指向你克隆的 URL。

5.3 添加远程仓库 (git remote add)

如果你先在本地初始化了一个仓库 (git init),然后想把它关联到一个空的远程仓库(比如你在 GitHub 上新建了一个仓库):

  1. 在远程服务商(如 GitHub)上创建一个新的空仓库。
  2. 获取远程仓库的 URL。
  3. 在你的本地项目目录下,添加远程仓库:
    bash
    git remote add origin <remote_repository_url>
    # 例如:git remote add origin https://github.com/your-username/your-project.git

    origin 是约定俗成的远程仓库别名,你可以使用其他名字,但 origin 是最常见的。

  4. 查看已配置的远程仓库:
    bash
    git remote -v

    这会显示所有远程仓库的别名及其 URL。

5.4 推送更改到远程仓库 (git push)

当你本地有新的提交后,你可以将这些提交推送到远程仓库,与团队成员共享。

“`bash
git push

例如:git push origin main

``
*
通常是origin
*
是你想要推送的分支,通常是mainmaster` 或你的功能分支。

第一次推送时,可能需要设置上游分支:
“`bash
git push -u origin main

或 git push –set-upstream origin main

``-u–set-upstream参数会将本地main分支与远程origin/main分支关联起来。之后,你就可以简单地使用git push(不带参数)来推送main` 分支的修改了。

5.5 从远程仓库拉取更改 (git pullgit fetch)

在开始工作之前,或者在你提交之前,最好先从远程仓库拉取最新的更改,以避免冲突。

  • git fetch:下载远程仓库的最新数据,但不合并。
    bash
    git fetch <remote_name>
    # 例如:git fetch origin

    git fetch 会将远程仓库的所有分支最新提交下载到你的本地,但它们会存储为远程分支的引用(例如 origin/main),而不会自动合并到你当前工作的本地分支。你可以通过 git log origin/main 查看远程分支的最新状态。

  • git pull:下载并合并远程仓库的最新数据。
    bash
    git pull <remote_name> <branch_name>
    # 例如:git pull origin main

    git pull 相当于 git fetchgit merge 的组合。它会首先从远程仓库下载最新提交,然后尝试将这些提交自动合并到你当前的本地分支。如果遇到冲突,你需要手动解决。

    如果你的本地分支已经与远程分支建立了追踪关系(例如你使用了 git push -u),那么你只需简单地:
    bash
    git pull

5.6 团队协作的典型流程

  1. 克隆仓库: git clone <repo_url>
  2. 创建功能分支: git checkout -b feature/your-feature-name
  3. 开发、修改、提交: 不断地 git add .git commit -m "..."
  4. 保持同步: 在开发过程中,经常从主线(如 main)拉取最新代码,以减少最终合并时的冲突。
    • 切换到主线:git checkout main
    • 拉取最新:git pull origin main
    • 切换回功能分支:git checkout feature/your-feature-name
    • 合并主线到功能分支:git merge main (解决冲突)
  5. 推送功能分支: git push origin feature/your-feature-name
  6. 发起拉取请求 (Pull Request / Merge Request): 在 GitHub/GitLab 等平台上,将你的功能分支合并到 main 分支。团队成员可以对你的代码进行审查(Code Review)。
  7. 合并到主线: 审查通过后,将功能分支合并到 main
  8. 删除远程功能分支: 如果不再需要,可以在平台或通过命令删除:git push origin --delete feature/your-feature-name
  9. 删除本地功能分支: git branch -d feature/your-feature-name

第六章:Git进阶技巧与最佳实践

掌握了上述核心操作,你已经可以游刃有余地管理大部分项目。但 Git 还有一些高级功能和最佳实践,可以进一步提升你的效率和代码质量。

6.1 忽略文件 (.gitignore)

有些文件不应该被 Git 追踪,例如:

  • 编译生成的文件(.o, .pyc, .class
  • IDE 或编辑器生成的配置文件(.idea/, .vscode/, .DS_Store
  • 依赖管理工具下载的包(node_modules/, vendor/
  • 敏感信息文件(config.ini, .env

你可以创建一个名为 .gitignore 的文件,列出你希望 Git 忽略的文件和目录。

.gitignore 规则:

  • 空行或 # 开头的行会被忽略。
  • 可以使用 * 作为通配符(匹配零个或多个字符)。
  • 可以使用 ? 匹配单个字符。
  • 使用 ! 开头表示不忽略(覆盖之前的规则)。
  • / 结尾表示匹配目录。
  • / 开头表示从项目根目录开始匹配。

示例 .gitignore 文件:

“`

忽略所有 .log 文件

*.log

忽略 build 目录

build/

忽略 node_modules 目录及其所有内容

node_modules/

忽略所有的 .DS_Store 文件,即使它们在子目录中

.DS_Store

忽略 config.ini 文件,但如果有一个文件名为 !config.ini 的,则不忽略

config.ini
!important_config.ini

忽略所有的 .a 文件,但保留 lib.a

*.a
!lib.a
“`

.gitignore 文件本身提交到仓库,这样团队成员也会共享这些忽略规则。

6.2 储藏更改 (git stash)

当你正在一个分支上工作,但突然需要切换到另一个分支处理紧急 Bug,而你当前的修改还没完成,不想提交时,git stash 就能派上用场。它会把你的工作区和暂存区的所有修改暂时“储藏”起来,让你的工作区变得干净。

  • 储藏当前修改:
    bash
    git stash save "正在开发新功能" # 也可以不加信息
  • 查看储藏列表:
    bash
    git stash list
  • 恢复最近一次储藏:
    bash
    git stash apply

    这会应用储藏,但保留储藏在列表中。
  • 恢复并删除最近一次储藏:
    bash
    git stash pop
  • 恢复指定的储藏:
    bash
    git stash apply stash@{1} # 恢复列表中的第二个储藏
  • 删除所有储藏:
    bash
    git stash clear

6.3 打标签 (git tag)

标签(Tag)用于标记项目中的某个特定版本,通常是发布版本(Release)。标签是对某个 commit 的一个固定引用,一旦创建就不会再改变。

  • 列出所有标签:
    bash
    git tag
  • 创建轻量标签 (Lightweight Tag): 只是一个指向特定 commit 的指针。
    bash
    git tag v1.0.0

    默认打在当前 HEAD 指向的 commit 上。你也可以指定 commit ID:git tag v1.0.0 <commit_id>
  • 创建附注标签 (Annotated Tag): 存储在 Git 数据库中,包含打标签者的名字、邮箱、日期,并可以添加注释。更推荐用于发布版本。
    bash
    git tag -a v1.0.0 -m "Release version 1.0.0"
  • 查看标签信息:
    bash
    git show v1.0.0
  • 将标签推送到远程仓库: 标签默认不会随着 git push 推送,需要单独推送。
    bash
    git push origin <tag_name> # 推送单个标签
    git push origin --tags # 推送所有本地标签
  • 删除标签:
    • 本地删除:git tag -d <tag_name>
    • 远程删除:git push origin --delete <tag_name> (注意先删除本地再删除远程)

6.4 重写历史 (git rebase)

git rebase 是一种强大的命令,用于将一系列提交“重新播放”到另一个基点上。它可以让你的提交历史变得更线性、更整洁。但它会改变现有提交的 SHA-1 ID,因此绝对不要对已经推送到远程仓库并与他人共享的提交使用 rebase

  • 基本用法: 假设你在 feature 分支上开发,同时 main 分支也有了新的提交。你想让 feature 分支的提交看起来像是直接基于 main 的最新提交开发的,而不是在旧的 main 上开发的。

    1. 切换到 feature 分支:git checkout feature
    2. 拉取 main 最新代码:git pull origin main (确保 main 本地是最新)
    3. 执行 rebase:git rebase main
      这会将 feature 分支上的所有提交一个个地应用到 main 分支的最新提交之后。
  • 交互式 rebase (git rebase -i): 这是 rebase 最强大的模式。你可以对一系列提交进行:

    • 修改提交信息 (reword)
    • 合并多个提交 (squash)
    • 删除提交 (drop)
    • 重新排序提交 (reorder)
    • 编辑提交 (edit)
      通常用于在发起 Pull Request 之前,整理自己的功能分支提交历史,使其更清晰。

    使用方法: git rebase -i HEAD~<n>git rebase -i <commit_id>
    HEAD~n 表示最近的 n 个提交,<commit_id> 表示该 commit 之前的历史)
    执行后会弹出一个交互式编辑器,你可以按照提示修改提交前的指令。

    再次强调:Rebase 会改写历史,只在本地分支或尚未推送到远程的私有分支上使用。

6.5 Git 工作流模式

虽然 Git 本身很灵活,但为了提高团队协作效率,业界发展出了一些常见的工作流模式:

  • GitHub Flow: 简单实用。一个 main (或 master) 分支作为主干,所有新功能、Bug 修复都从 main 分支拉出特性分支(feature branch)进行开发,完成后通过 Pull Request 审查并合并回 mainmain 分支的代码始终保持可部署状态。
  • Git Flow: 更复杂,适用于需要严格版本控制和多阶段发布的项目。它引入了 master(稳定发布版)、develop(集成开发版)、feature(功能开发)、release(发布准备)、hotfix(紧急修复)等多个长期分支。

对于初学者和小型团队,GitHub Flow 往往足够且更易上手。

6.6 提交信息规范

规范的提交信息能够极大地提高项目的可读性和维护性。可以遵循以下约定:

  • 主题行 (Subject Line): 简洁明了,概括本次提交的目的,不超过 50-72 个字符。
    • 使用动词开头,如 feat (新功能), fix (修复), `docs (文档), style (代码格式), refactor (重构), test (测试), chore (日常任务) 等。
    • feat: add user profile page
    • fix: resolve login authentication issue
  • 空一行: 主题行后留一个空行。
  • 正文 (Body): 详细描述本次提交的修改内容、原因、解决方案、涉及范围、潜在影响等。
    • 使用当前时态的祈使语气(例如 “Add feature” 而不是 “Added feature”)。
    • 可以引用问题追踪系统中的 issue ID (例如 Fixes #123)。

第七章:总结与展望

恭喜你!通过这篇教程,你已经掌握了 Git 的核心概念和大部分常用操作。你现在应该能够:

  • 理解版本控制的重要性。
  • 在本地初始化、克隆、管理 Git 仓库。
  • 掌握工作区、暂存区、版本库的概念。
  • 进行文件的添加、提交、查看历史和差异。
  • 高效地使用分支进行并行开发和合并。
  • 与远程仓库协作,进行推送和拉取。
  • 运用 .gitignore 忽略不必要的文件。
  • 使用 git stash 临时保存工作。
  • 打标签来标记重要版本。
  • 了解 git rebase 的强大与风险。
  • 遵循一些 Git 最佳实践。

Git 的学习是一个持续的过程,它的功能远不止这些。以下是一些你可以继续探索的方向:

  • 图形化界面工具: 如果你对命令行不太习惯,可以尝试 Sourcetree, GitKraken, TortoiseGit, VS Code 内置的 Git 界面等。
  • 更复杂的 Git 命令: bisect (二分查找 Bug), cherry-pick (挑选单个提交), reflog (恢复误操作) 等。
  • Git Hooks: 在特定 Git 事件发生时自动执行脚本。
  • 持续集成/持续部署 (CI/CD): 将 Git 与自动化构建、测试、部署流程结合。
  • 深入理解 Git 内部原理: Git 的对象模型(blob, tree, commit, tag)。

最重要的是:实践! 没有任何理论知识能替代实际操作。现在就开始用 Git 管理你的每一个项目,从个人小项目到团队大项目,不断尝试,不断犯错,再不断解决,你很快就能成为一名 Git 大师。

祝你在代码管理的道路上一帆风顺!

滚动至顶部