Git 从入门到实践

Git 作为现代软件开发中的不可或缺工具,为团队协作和版本控制提供了强大支持。
本文将介绍 Git 的基本概念、常用命令以及在实际开发中的应用,帮助读者理解 Git 的工作原理和基本使用方法。
1 认知 Git
在软件开发的世界中,版本控制是一项关乎效率、协作和可追溯性的核心实践。随着代码规模和项目复杂性的不断增长,版本控制成为了不可或缺的工具,旨在管理代码的演变历程、跟踪变更以及促进团队的协同开发。而在版本控制领域,Git 以其强大的功能和灵活的架构崭露头角,成为当今最受欢迎和广泛应用的分布式版本控制系统。
1.1 什么是版本控制?
版本控制是一种用于追踪文件和项目中的变化的技术和实践。它可以记录文件的每一次修改,包括添加、删除、修改等操作,从而形成一个历史记录。这个历史记录不仅仅是简单的时间线,还能够帮助开发者跟踪每个变更的作者、时间和目的,同时方便地回滚到之前的状态。版本控制不仅适用于代码,还可以应用于文档、配置文件以及任何需要追踪变化的内容。
1.2 什么是 Git
Git 是一种分布式版本控制系统,由 Linus Torvalds 在 2005 年创立。与传统的集中式版本控制系统不同,Git 在每个开发者的本地都维护了完整的代码仓库副本,这意味着开发者可以在没有网络连接的情况下进行工作,极大地提高了协作的灵活性和效率。
Git 拥有以下特点:
分布式架构: Git的分布式架构赋予了开发者更大的自由度,能够在不同分支上进行并行开发,而不会受到中央服务器的限制。这种架构还提供了本地提交、分支切换等操作的快速性能。
快速和高效: Git的设计注重性能,使得在大型项目中也能够迅速处理变更和提交。它采用了一系列优化策略,使得代码库的管理和浏览变得轻松而迅捷。
分支管理: Git的强大分支管理功能允许开发者在不同分支上独立工作,并能够轻松合并不同分支的变更。这为并行开发、特性隔离和Bug修复提供了良好的支持。
版本历史: Git记录了每次提交的详细信息,包括作者、时间戳和提交注释。这使得团队可以追溯每一行代码的变更,更轻松地识别和解决问题。
社区支持: Git已经成为开源社区和工业界的标准,拥有广泛的文档、工具和资源。这使得学习和使用Git变得更加容易。
1.3 安装及配置
关于 Git 的安装,本文就不再赘述,本小节主要说明如何做一些简单配置,有需要安装教程请参考 Git——1.5 起步 - 安装 Git
1.3.1 配置用户信息
使用如下代码配置用户信息,将<your userName>
改为你的用户信息,<your email>
改为你的邮箱账户。
1 | git config --global user.name "<your userName>" |
gitBash 查看配置信息
1 | git config --global user.name |
1.3.2 为常用指令配置别名
使用下面的命令创建别名,将 <alias>
替换为别名名称,将 <command>
替换为要使用别名的命令:
1 | git config --global alias.<alias> <command> |
一个一个命令去设置很是麻烦,所以我们也可以写一个.bashrc
来存放别名
1 | 创建文件 |
2 Git 的基础概念
2.1 仓库(Repository)是什么?
在 Git 中,仓库是存储项目所有版本历史和文件的地方。它包含了整个项目的信息,包括每次提交(commit)的变更内容、提交者、时间戳等。一个仓库可以保存在本地计算机上,也可以通过远程仓库与团队成员共享。每个开发者都可以通过克隆仓库或者从远程仓库中拉取最新的代码来开始工作。
2.2 工作区、暂存区和版本历史的关系
工作区: 工作区是你在计算机上实际编辑文件的地方,即你正在进行开发和修改的地方。
暂存区(Stage): 暂存区是一个中间状态,用于暂时保存你想要提交的更改。在你完成某项修改后,将更改添加到暂存区,然后一次性提交这些更改。这允许你精细地控制提交的内容,将逻辑相关的变更一并提交。
版本历史(Commit History): 当你认为暂存区中的更改已经达到一个有意义的阶段时,你可以将暂存区的内容提交到版本历史中,这个操作称为提交(commit)。每次提交会生成一个唯一的标识符(commit hash),用于标记这次提交和其对应的变更。
2.3 提交(Commit):如何记录代码的变化
提交是Git中最重要的概念之一,它表示对代码的一次有意义的变更。一个提交记录了你的更改,同时包括了一个描述性的提交消息,用于解释这次变更的目的。提交的流程通常是:
1.在工作区进行代码修改。
2.将想要提交的更改使用git add
命令添加到暂存区。
3.使用git commit
命令将暂存区的更改提交到版本历史,并附带一条有意义的提交消息。
2.4 分支(Branch):管理不同的开发线路
分支是Git中的一个重要概念,它允许开发者在不影响主线代码的情况下开展新的工作。通过创建分支,你可以在分支上进行开发,而主线代码仍然保持原样。这使得不同功能的开发可以同时进行,而不会相互干扰。一般来说,项目的默认分支是master
(或main
),但你可以创建任意数量的分支。常见的分支操作包括创建、切换、合并和删除。
2.5 合并(Merge)和重置(Reset):整合和撤销变更
合并(Merge): 当你在不同分支上进行了独立开发,希望将一个分支的变更整合到另一个分支时,可以使用合并操作。合并会将两个分支的历史和代码变更合并成一个新的提交,这个提交将包含两个分支的变更。
重置(Reset): 重置是撤销操作的一种,可以用于撤销提交或者将分支的指针移动到不同的提交位置。有三种主要的重置模式:
--soft
仅移动分支指针,不改变工作区和暂存区;--mixed
移动分支指针并清除暂存区;--hard
移动分支指针、清除暂存区和工作区,慎用,会导致未提交的变更丢失。在后文第 3.8 小节 将详细讲解重置的基本使用。
这些 Git 基础概念构成了使用 Git 的核心,理解它们将帮助你更好地管理代码的变更、协同开发和保持项目的整洁与可维护性。
3 Git 的日常使用
3.1 Git 的工作流程
在学习 Git 的日常使用之前,我们先来了解一下 Git 的工作流程:
1. clone(克隆): 从远程仓库中克隆代码到本地仓库
2. checkout(检出): 从本地仓库中检出一个仓库分支然后进行修订
3. add(添加): 在提交前先将代码提交到暂存区
4. commit(提交): 提交到本地仓库。本地仓库中保存修改的各个历史版本
5. fetch (抓取): 从远程库,抓取到本地仓库,不进行任何的合并动作,一般操作比较少。
6. pull (拉取): 从远程库拉到本地库,自动进行合并 (merge),然后放到到工作区,相当于fetch+merge
7. push(推送): 修改完成后,需要和团队成员共享代码时,将代码推送到远程仓库
以上使用具体命令稍后会进行讲解,相信在读者学完全部命令后再来查看该工作流程,就会对 Git 的工作流程有一个更深的理解。
3.2 创建仓库:初始化和克隆
初始化仓库: 使用
git init
命令可以在当前目录创建一个新的Git仓库,将其初始化为Git可管理的仓库。执行git init
后,Git 会在当前目录下创建一个名为.git
的子目录,该子目录包含了 Git 仓库的所有信息和元数据。这个仓库将记录你项目中所有文件的历史版本、修改记录以及分支等信息,以便你可以轻松地进行版本控制、协作和管理。以下是使用git init
命令初始化一个新的 Git 仓库的一般步骤:- 打开终端或命令行界面。
- 导航到你要创建仓库的目录。
- 运行以下命令:
git init
克隆仓库: 使用
git clone <repository_url>
命令可以从远程仓库克隆一份完整的副本到本地计算机。它是将整个远程仓库完整地复制到本地的操作,包括所有的版本历史、分支、标签和文件内容。通过使用git clone
,你可以在本地创建一个与远程仓库完全一致的副本,以便在本地进行开发、修改和提交。git clone
常用于以下场景:- 当你想要在本地开始一个新的项目时,可以通过克隆现有的远程仓库来获得基础代码。
- 当你想要为某个开源项目做出贡献时,可以将项目的代码克隆到本地,进行修改,然后提交合并请求。
- 当你需要在多台计算机上协作开发同一个项目时,可以在每台计算机上克隆相同的仓库,以便同步工作。
3.3 添加和提交:管理代码变更
添加(Add): 使用
git add <file_name>
命令可以将文件从工作区添加到暂存区,准备提交。常见的用法有以下几种:- 添加单个文件:
1
git add filename
- 添加多个文件:
1
2
3
4
5
6
7
8
9git add file1 file2 file3
```
- 添加当前目录下的所有文件(递归地):
```SHELL
git add .
```
- 添加当前目录下的所有文件及子目录(递归地):
```SHELL
git add --all
- 添加单个文件:
git add 命令的选项可以根据需求进行调整,例如:
- -A 或 –all:添加所有更改(包括删除的文件和目录)。
- -u 或 –update:添加已修改或已删除的文件,但不包括新增的文件。
- -p 或 –patch:交互式地选择部分更改进行暂存。
例如,使用 -A 选项的命令如下:1
git add -A
提交(Commit): 使用
git commit -m "Commit message"
命令可以将暂存区的更改提交到版本历史。提交时附带的提交消息应该清晰地描述这次提交的变更内容。除了-m
选项外,git commit
还有其他选项和用法,例如:- -a:自动将已经被 Git 跟踪且已修改的文件添加到暂存区,然后提交。这是快捷方式,适用于一些小的修改。
- -am:结合了 -a 和 -m 选项,可以在提交时自动添加已修改的文件,并提供提交消息。
- -v:在提交消息前显示本次提交的具体更改内容。
- -i:进入交互式提交模式,可以逐个确认暂存区中的文件是否要被包含在提交中。
提交是 Git 中的不可逆操作,一旦提交后,你可以通过 Git 的一些其他命令来查看、比较或回滚提交,但直接修改提交内容可能会导致问题。因此,在提交前请确保你的更改已经被正确地暂存,并且提交消息清晰明确。
3.4 更新代码:拉取(Pull)和推送(Push)
拉取(Pull): 使用
git pull <remote_name> <branch_name>
命令可以将远程仓库中的最新代码拉取到本地分支,确保你的工作区保持最新。它实际上是两个操作的组合:git fetch
和git merge
。具体来说,git pull
命令会执行以下步骤:- 首先,它会运行
git fetch
命令,从远程仓库下载最新的提交、分支和标签,但并不会合并这些更改到你的本地分支。 - 然后,它会运行
git merge
命令,将从远程仓库获取的最新提交合并到你当前所在的本地分支。
如果合并过程中出现冲突,你需要解决这些冲突才能完成合并。
- 首先,它会运行
推送(Push): 使用
git push [-f] [--set-upstream] <remote_name> <branch_name>
命令可以将你的本地提交推送到远程仓库,共享你的代码变更给团队成员。- 如果远程分支名和本地分支名称相同,则可以只写本地分支
1
git push origin master
- -f 表示强制覆盖
- –set-upstream 推送到远端的同时并且建立起和远端分支的关联关系。
1
git push --set-upstream origin master
- 如果当前分支已经和远端分支关联,则可以省略分支名和远端名。
git push
将 master 分支推送到已关联的远端分支。
<remote_name>
是远程仓库的名称,通常是 origin,但也可以是其他自定义的远程仓库名称。<branch_name>
是要推送的本地分支的名称。
在执行
git push
之前,通常你需要先将本地的提交通过 git commit 命令保存到本地仓库。- 如果远程分支名和本地分支名称相同,则可以只写本地分支
3.5 查看仓库当前状态 :git status
git status
是一个用于查看 Git 仓库当前状态的命令。当你在 Git 仓库中工作时,可能会进行各种操作,如添加、修改或删除文件,以及进行提交等。git status
命令可以让你随时查看当前工作目录和暂存区的状态,以帮助你了解哪些文件已被修改、添加或删除,哪些文件已经被暂存,以及是否有待提交的更改。使用 git status
命令,你会得到关于以下几个方面的信息:
- 未暂存的更改:这些是在工作目录中被修改但尚未添加到暂存区的文件。
- 暂存的更改:这些是已经通过
git add
命令添加到暂存区的文件,等待被包含在下一次提交中。 - 未跟踪的文件:这些是在工作目录中存在,但尚未被 Git 跟踪的文件。这些文件不会包含在下一次提交中,除非你使用
git add
将它们添加到暂存区。
git status
命令的输出会告诉你每个文件的状态,以及你需要执行的下一步操作,如添加文件到暂存区或提交更改。示例:
1 | git status |
从这个示例输出中,你可以看到哪些文件已被修改,哪些文件已被暂存,以及有哪些未跟踪的文件。
3.6 分支管理:创建、切换、合并与删除分支
查看分支: 使用
git branch
命令可以查看本地分支创建分支: 使用
git branch <branch_name>
命令可以创建一个新的分支。该分支将从当前分支派生,并包含相同的代码。切换分支: 使用
git checkout [-b] <branch_name>
命令可以切换到另一个分支,使你能够在不同分支上进行不同的开发。合并分支: 使用
git merge <branch_name>
命令可以将另一个分支的变更合并到当前分支中。这通常用于整合不同特性或修复到主分支。删除分支: 使用
git branch -d <branch_name>
命令可以删除已合并的分支,确保清理不再需要的分支。
3.7 解决冲突:处理不同分支之间的冲突
在分支合并时,可能会出现冲突,即两个分支对同一部分代码作出了不同的修改。解决冲突的一般步骤包括:
1.使用
git pull
拉取远程分支的最新代码。
2.在代码中找到并解决冲突部分。
3.添加解决后的文件到暂存区。
4.提交解决冲突的更改。
3.8 重置状态
git reset
是一个用于将 Git 仓库的 HEAD 和暂存区重置到指定状态的命令。通过 git reset
,可以取消已暂存的更改、撤销提交、移动 HEAD 指针以及管理版本控制历史。git reset
命令有多种选项,常见的选项包括:
git reset --soft <commit>
: 将 HEAD 移动到指定的提交,但不会修改暂存区和工作目录。这样可以撤销最近的提交,将它们变为未暂存状态,以便你可以修改后重新提交。git reset --mixed (默认选项) <commit>
:将 HEAD 移动到指定的提交,并且会取消暂存区的更改,但不会影响工作目录。这可以用来撤销最近的提交和暂存的更改,让你可以重新选择并提交需要的更改。git reset --hard <commit>
:将 HEAD 移动到指定的提交,并且会取消暂存区和工作目录的更改,使你的仓库状态与指定的提交完全一致。谨慎使用这个选项,因为它会永久删除未提交的更改。<commit>
可以是 提交的哈希值 / 分支名 / 标签名 通常情况下,使用哈希值是最准确和明确的,因为每个提交的哈希值是唯一的。但是,如果你知道分支名或标签名,也可以使用它们来指定要重置到的提交。<commit>
可以使用git log
指令查看获取。如何查看已经删除的记录?
- 使用
git reflog
命令查看本地仓库中的引用日志(reflog)恢复误操作、查看过去的操作记录以及回滚到之前的状态。
- 使用
除了上述常见选项外,还有其他选项可以与 git reset
命令一起使用,以实现更精细的重置操作。例如,你可以使用 git reset <file>
来取消暂存指定文件,或者使用 git reset HEAD~1
来将 HEAD 移动到前一个提交。
请注意,git reset
可以改变你的仓库状态,包括删除未提交的更改和提交记录。在使用这个命令时,请务必谨慎操作,以免不小心丢失重要的更改或提交历史。
3.9 查看提交日志(log)
使用 git log [option]
命令可以显示仓库历史记录中的所有提交,option 为可用参数:
- option
- –all 显示所有分支
- –pretty=oneline 将提交信息显示为一行
- –abbrev-commit 使得输出的commitId更简短
- –graph 以图的形式显示
这里我们在 1.3.2 为常用指令配置别名的.bashrc
配置 中,为 git log 配置了上述全部参数,所以后续可以直接使用指令 gl。
4 高级 Git 操作
4.1 重写历史:变基(Rebase)和交互式重写(Interactive Rebase)
变基(Rebase): 使用
git rebase <base_branch>
命令可以将当前分支的提交移动到目标分支的最新提交之上,以实现整洁的提交历史。这有助于保持分支的整洁性,但需要注意,对于已经共享的提交,变基可能会带来问题。交互式重写(Interactive Rebase): 交互式重写允许你更细粒度地控制提交历史的修改。使用
git rebase -i <base_commit>
命令可以在交互模式下编辑、合并、重排提交,还可以编辑提交消息。
4.2 子模块:管理项目中的子项目
子模块的添加: 使用
git submodule add <repository_url> <path>
命令可以将另一个Git仓库添加为你项目的子模块。子模块的更新: 在父项目中使用
git submodule update
命令可以拉取子模块的最新代码。子模块的克隆: 使用
git clone --recursive <repository_url>
命令可以克隆父项目及其子模块的代码。
4.3 标签(Tag):为代码库中的重要节点打上标记
创建标签: 使用
git tag <tag_name> <commit>
命令可以在特定提交上创建一个标签。标签通常用于版本发布、里程碑或重要事件。列出标签: 使用
git tag
命令可以列出所有标签。查看标签详细信息: 使用
git show <tag_name>
命令可以查看特定标签的详细信息。
4.4 忽略文件:配置 .gitignore
以排除特定文件
.gitignore
文件: 创建一个名为.gitignore
的文件,其中列出你希望 Git 忽略的文件、目录、模式等。常用模式: 在
.gitignore
文件中可以使用通配符、正则表达式等模式,以排除特定类型的文件(例如编译产物、临时文件等)。示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# Maven
target/
# Spring Boot
mvnw
mvnw.cmd
.idea
# IntelliJ IDEA
.idea/
*.iml
*.iws
*.ipr
......通过深入了解这些高级的 Git 操作,你将能够更好地处理代码历史的整理、子模块的管理、重要节点的标记以及文件的排除,从而提升项目的可维护性和开发效率。
5 团队协作与远程仓库
5.1 远程仓库管理:添加、删除和重命名远程仓库
- 查看远程仓库: 使用
git remote -v
列出所有远程仓库及其 URL。这个命令会显示远程仓库的名称以及它们的 URL。- 使用示例:
1
2
3
4
5
6
7只显示当前仓库配置的所有远程仓库的简称,相当于运行`git remote -v`的简化版本
git remote
origin
git remote -v
origin git@github.com:youfenghhd/test.git (fetch)
origin git@github.com:youfenghhd/test.git (push)
- 使用示例:
- 添加远程仓库: 使用
git remote add <remote_name> <repository_url>
命令可以将一个远程仓库添加到你的本地项目。远程仓库通常用于团队协作和代码共享。- 使用示例:
1
git remote add origin git@github.com:youfenghhd/test.git
- 使用示例:
- 删除远程仓库: 使用
git remote remove <remote_name>
命令可以移除你本地项目中的一个远程仓库配置。- 使用示例:
1
git remote remove upstream
- 使用示例:
- 重命名远程仓库: 使用
git remote rename <old_remote_name> <new_remote_name>
命令可以重命名已存在的远程仓库配置。- 使用示例:
1
git remote rename origin main
- 使用示例:
- 修改远程仓库的 URL 使用
git remote set-url <name> <new-url>
修改已配置远程仓库的 URL 。- 使用示例:
1
git remote set-url origin git@github.com:youfeng/test1.git
- 使用示例:
5.2 协作模式:多人开发的最佳实践
分支独立: 为每个功能、修复或任务创建独立的分支,每位开发者应在自己的分支上进行开发,避免直接在主分支上进行更改。
频繁提交: 将开发的变更分成小而有意义的提交,以便团队成员能够更容易地理解和审查你的代码。
代码审查(Code Review): 通过代码审查,团队成员可以对彼此的代码进行检查和提出建议,提高代码质量和可维护性。
持续集成(CI): 将自动化测试和构建流程集成到代码仓库中,确保每次提交都经过自动化测试,减少错误进入主分支的可能性。
5.3 分支策略:选择适合团队的分支模型
主分支(Main Branch): 通常是 master 或 main 分支,用于存放稳定和发布的代码。
开发分支: 使用一个专门的开发分支(如 develop)来集成各种功能和修复,以便在主分支之前进行测试和集成。
特性分支(Feature Branches): 用于开发特定功能或特性的分支,从主分支派生,开发完成后合并回主分支。
发布分支(Release Branches): 用于准备发布版本的分支,从主分支派生,用于修复bug、测试和准备发布。
热修复分支(Hotfix Branches): 用于紧急修复线上问题的分支,从主分支或发布分支派生,修复完成后合并回主分支和发布分支。
选择适合团队工作流和项目特点的分支策略是至关重要的。合理的分支策略可以减少冲突,提高协作效率,确保代码的质量和稳定性。通过实践这些团队协作与远程仓库的最佳实践,你可以在团队中更加高效地协同开发,确保代码的一致性,同时减少潜在的冲突和问题。
6 故障排除与最佳实践
6.1 常见问题与解决方案
问题: 合并分支时出现冲突。
解决方案: 使用git status
查看冲突文件,手动解决冲突,然后使用git add
标记已解决的文件,并继续合并操作。问题: 本地仓库和远程仓库的分支不同步。
解决方案: 使用git pull
拉取远程分支的最新代码,确保本地分支与远程分支同步。问题: 误删除了重要文件。
解决方案: 如果你没有提交删除前的版本,可以使用git checkout
从历史记录中恢复文件;如果已提交,可以使用git log
找到删除前的提交,然后使用git cherry-pick
将文件恢复到当前分支。问题: 代码库中的某个功能出现问题。
解决方案: 使用git bisect
命令可以快速定位问题的引入提交,从而找到导致问题的提交,然后进行修复。
6.2 提交规范:有意义的提交信息
为了更好地维护代码库的历史和理解每次变更,遵循有意义的提交规范是至关重要的。
- 使用简洁而具体的提交消息,清楚地描述你的变更目的。
- 使用动词原形开头,如
"Fix", "Add", "Update"
。 - 添加适当的上下文信息,如果有关联的问题或任务,可以添加关键字或链接。
- 避免使用含糊不清的提交消息,如
"Fix some bugs"
,这不利于日后的追溯。
示例:
1 | Fix: Correct null pointer exception in user login |
6.3 分支保护:保护重要分支免受误操作影响
分支保护: 对于主要分支(如 master 或 main),可以启用分支保护机制,以确保只有特定权限的成员能够推送变更,从而减少误操作和意外的代码变更。
Pull Request(PR)审查: 使用 Pull Request 机制,要求团队成员在推送代码前创建 Pull Request,经过审核后才能合并。这有助于保持代码质量和一致性。
持续集成: 在分支保护中集成持续集成,确保只有通过自动化测试的代码才能合并到主分支,防止不稳定的代码进入代码库。
以上最佳实践和解决方案将帮助你避免常见的问题,保持代码库的质量,并提高团队的协作效率。
结语
在现代软件开发中,Git 已经成为不可或缺的工具,为团队协作、代码管理和版本控制提供了强大的支持。通过掌握 Git 的基础操作,你可以轻松地管理代码变更、创建分支、合并变更,并与团队成员共享代码。通过高级操作如变基、子模块管理、标签使用以及分支策略的选择,你可以进一步提高代码质量、团队效率和开发流程的可控性。
在团队协作方面,遵循最佳实践如合理的分支管理、规范的提交信息和分支保护,可以确保团队协作的有序性、代码库的稳定性以及减少潜在的冲突和误操作。
掌握Git的使用不仅对个人的开发效率有所提升,更有助于团队在项目开发中保持协调一致。通过将这些知识融入到你的日常工作流中,你将能够更好地应对挑战、协同工作,并构建出更加可靠、高效的软件项目。
- 标题: Git 从入门到实践
- 作者: HYF
- 创建于 : 2023-08-17 23:35:19
- 更新于 : 2024-07-27 21:21:52
- 链接: https://youfeng.ink/Git-a2c56c0d47a8/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。