Git,是目前世界上,最流行、最强大的分布式版本控制系统。

对于程序员来说,Git,已经成为了必备技能。无论是个人开发,还是团队协作,Git,都能帮助我们,更好地管理代码版本,追踪代码变更,进行团队协作。可以说,不会用Git的程序员,不是一个合格的程序员。

我自己,从大学开始接触Git,到现在工作多年,每天都在使用Git。从最初的只会add、commit、push,到后来能够熟练使用分支、合并、变基、撤销、回滚等高级功能,一路走来,踩了不少坑,也总结了不少经验。我见过太多的开发者,因为不会用Git,而导致代码丢失、版本混乱、协作冲突等问题。其实,只要掌握了Git的基本原理和常用命令,这些问题,都能避免。

2015年,Git,已经成为了版本控制系统的绝对主流。GitHub,作为最大的Git托管平台,已经拥有了数百万的开发者和数千万的代码仓库。无论是开源项目,还是商业项目,大多数都在使用Git进行版本控制。SVN、CVS等传统的集中式版本控制系统,已经逐渐被淘汰。

今天,分享Git版本控制,从基本原理到常用命令,从分支策略到团队协作,从常见问题到最佳实践,全方位讲解Git的使用方法和技巧,帮你掌握这个程序员的协作利器。

什么是版本控制

在讲Git之前,先简单介绍一下,什么是版本控制。

版本控制(Version Control),是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。

简单来说,版本控制,就是帮你管理文件的不同版本。你可以随时,把文件恢复到之前的某个版本;可以查看,文件在什么时候,被谁修改了,修改了什么内容;可以和其他人,协作开发同一个项目,而不会互相覆盖对方的代码。

没有版本控制的时候,开发者,通常用"复制文件夹"的方式,来管理版本。比如,把项目文件夹,复制一份,命名为"项目_20151105",然后在新的文件夹里修改。这种方式,非常原始,也非常容易出问题:

  • 版本多了,不知道哪个版本,是最新的
  • 想找某个历史版本,要一个个文件夹打开看
  • 两个人同时修改同一个文件,很容易互相覆盖
  • 想比较两个版本的差异,非常麻烦
  • 占用大量磁盘空间

而版本控制系统,就是为了解决这些问题而诞生的。它,能自动记录文件的每次变更,能方便地查看和恢复历史版本,能支持多人协作开发,能节省磁盘空间。

版本控制系统,主要分为两类:

  1. 集中式版本控制系统:如SVN、CVS。所有的版本数据,都存储在中央服务器上。开发者,从中央服务器,检出代码,修改后,提交回中央服务器。缺点是,必须联网才能工作;中央服务器挂了,所有人都无法工作;中央服务器的数据丢了,所有版本都丢了。
  2. 分布式版本控制系统:如Git、Mercurial。每个开发者的电脑上,都有一个完整的版本库,包含所有的历史版本。开发者,可以在本地,提交代码,查看历史,创建分支,不需要联网。只有在需要和其他人协作时,才需要联网,推送或拉取代码。优点是,离线也能工作;安全性高,每个人的电脑上,都有完整的备份;分支和合并,非常强大和灵活。

Git,就是分布式版本控制系统的代表,也是目前最流行、最强大的版本控制系统。

Git的基本原理

要学好Git,首先要理解Git的基本原理。Git的原理,和其他版本控制系统,有很大的不同。

1. Git记录的是快照,不是差异

很多版本控制系统(如SVN),记录的是文件的差异。也就是说,每次提交,只记录文件相对于上一个版本,修改了哪些内容。

而Git,记录的是文件的快照。也就是说,每次提交,Git会把当时所有文件的状态,拍一张"快照",保存下来。如果某个文件,没有修改,Git不会重复保存,而是保留一个链接,指向之前保存的相同文件。

这种方式,让Git的分支和合并,非常高效。因为,创建一个分支,本质上,就是创建一个指向某个快照的指针,几乎不占用任何空间。

2. Git的三个区域

Git,有三个重要的区域:工作区、暂存区、版本库。

  • 工作区(Working Directory):就是你在电脑里,能看到的项目目录。你在工作区里,修改、添加、删除文件。
  • 暂存区(Staging Area / Index):是一个文件,保存了下次将提交的文件列表信息。一般,在Git仓库目录中,叫.git/index。你用git add命令,把工作区的修改,添加到暂存区。
  • 版本库(Repository):就是.git目录,里面保存了所有的版本数据。你用git commit命令,把暂存区的内容,提交到版本库,形成一个新的版本。

这三个区域的关系,是Git最核心的概念。理解了这三个区域,就理解了Git的基本工作流程。

3. Git的工作流程

Git的基本工作流程,是这样的:

  1. 在工作区,修改文件
  2. git add,把修改的文件,添加到暂存区
  3. git commit,把暂存区的内容,提交到版本库,形成一个新的版本

就是这么简单。这三个步骤,就是Git最基本的操作。

4. Git的对象

Git,内部有四种对象:

  • blob对象:存储文件的内容。每个文件的内容,对应一个blob对象。
  • tree对象:存储目录结构。记录了目录下,有哪些文件和子目录,以及它们对应的blob对象或tree对象的哈希值。
  • commit对象:存储一次提交的信息。包括提交的作者、时间、提交信息,以及对应的tree对象的哈希值,还有父提交的哈希值。
  • tag对象:存储一个标签,指向某个commit对象。

Git,用SHA-1哈希值,来标识每个对象。每个对象的内容不同,哈希值就不同。Git,通过这些对象和哈希值,构建了整个版本库。

5. Git的引用

Git的引用(refs),是指向某个commit对象的指针。主要有:

  • 分支(branch):指向某个commit对象的指针。你在某个分支上提交,分支指针,会自动向前移动。
  • 标签(tag):指向某个commit对象的指针,通常不会移动。用于标记重要的版本,如发布版本。
  • HEAD:指向当前所在分支的指针。你切换分支,HEAD就指向新的分支。

理解了Git的对象和引用,就理解了Git的内部原理。

Git基本命令

1. 配置Git

在使用Git之前,需要先配置一下你的用户名和邮箱,因为每次Git提交,都会使用这些信息。

# 配置用户名
git config --global user.name "Your Name"

# 配置邮箱
git config --global user.email "your@email.com"

# 配置默认编辑器
git config --global core.editor vim

# 配置换行符处理(Windows)
git config --global core.autocrlf true

# 配置换行符处理(Mac/Linux)
git config --global core.autocrlf input

# 查看配置
git config --list

# 查看某项配置
git config user.name

2. 创建仓库

有两种方式,创建Git仓库:

# 方式一:在当前目录,初始化一个新的Git仓库
git init

# 方式二:克隆一个已有的远程仓库
git clone https://github.com/user/repo.git

# 克隆时,指定本地目录名
git clone https://github.com/user/repo.git myrepo

3. 查看状态

# 查看工作区和暂存区的状态
git status

# 简洁模式
git status -s

git status,是最常用的命令之一。它会告诉你,哪些文件被修改了,哪些文件在暂存区,哪些文件没有被跟踪。

4. 添加文件到暂存区

# 添加指定文件到暂存区
git add filename

# 添加所有修改和新增的文件到暂存区
git add .

# 添加所有修改、新增、删除的文件到暂存区
git add -A

# 交互式添加
git add -i

# 补丁模式,逐块选择要添加的内容
git add -p

5. 提交

# 提交暂存区的内容,打开编辑器输入提交信息
git commit

# 提交,并直接指定提交信息
git commit -m "提交信息"

# 提交所有已跟踪的文件的修改(不需要先git add)
git commit -a -m "提交信息"

# 修改上一次提交
git commit --amend

# 修改上一次提交的提交信息
git commit --amend -m "新的提交信息"

6. 查看历史

# 查看提交历史
git log

# 简洁显示,每个提交一行
git log --oneline

# 显示最近N次提交
git log -n 5

# 显示提交的差异
git log -p

# 显示提交的统计信息
git log --stat

# 图形化显示分支合并历史
git log --graph --oneline --all

# 按作者筛选
git log --author="username"

# 按时间筛选
git log --since="2015-01-01" --until="2015-12-31"

# 查看某个文件的提交历史
git log filename

# 查看提交历史,包括被重命名的文件
git log --follow filename

7. 查看差异

# 查看工作区和暂存区的差异
git diff

# 查看暂存区和版本库的差异
git diff --cached
# 或
git diff --staged

# 查看工作区和版本库的差异
git diff HEAD

# 查看两个提交之间的差异
git diff commit1 commit2

# 查看两个分支之间的差异
git diff branch1 branch2

# 查看某个文件的差异
git diff filename

# 统计差异的行数
git diff --stat

8. 撤销操作

# 撤销工作区的修改(恢复到暂存区的状态)
git checkout -- filename
# 或(Git 2.23+)
git restore filename

# 撤销暂存区的添加(把暂存区的文件,放回工作区)
git reset HEAD filename
# 或(Git 2.23+)
git restore --staged filename

# 撤销工作区和暂存区的修改(恢复到最近一次提交的状态)
git checkout HEAD -- filename
# 或
git restore --source=HEAD --staged --worktree filename

# 撤销最近一次提交(保留修改在工作区)
git reset --soft HEAD~1

# 撤销最近一次提交(保留修改在暂存区)
git reset --mixed HEAD~1
# 或直接
git reset HEAD~1

# 撤销最近一次提交(丢弃修改,危险!)
git reset --hard HEAD~1

# 撤销到某个提交(丢弃之后的所有提交,危险!)
git reset --hard commit_id

注意:git reset --hard,会丢弃工作区和暂存区的修改,非常危险!使用前,一定要确认,不需要那些修改了。

9. 删除和移动文件

# 删除文件,并把删除操作添加到暂存区
git rm filename

# 删除文件,但保留在工作区(只从Git中移除跟踪)
git rm --cached filename

# 重命名/移动文件,并把操作添加到暂存区
git mv oldname newname

# 这相当于:
# mv oldname newname
# git rm oldname
# git add newname

10. 忽略文件

有些文件,不需要纳入Git的版本控制,如编译产物、日志文件、配置文件、依赖库目录等。可以创建一个.gitignore文件,来指定要忽略的文件。

.gitignore文件的格式:

# 注释
# 忽略所有的.log文件
*.log

# 忽略node_modules目录
node_modules/

# 忽略根目录下的dist目录
/dist

# 忽略所有目录下的tmp目录
tmp/

# 忽略所有的.o和.a文件
*.[oa]

# 不忽略(取反)某个文件,即使前面规则忽略了它
!important.log

# 忽略doc目录下的所有txt文件,但不包括子目录
doc/*.txt

# 忽略doc目录下所有的pdf文件,包括子目录
doc/**/*.pdf

GitHub,提供了一个常用的.gitignore模板库,可以根据项目类型,选择合适的模板:https://github.com/github/gitignore

分支管理

分支,是Git最强大的功能之一。分支,让你可以,在不影响主线的情况下,开发新功能、修复bug、做实验。

1. 查看分支

# 查看本地分支
git branch

# 查看所有分支(包括远程分支)
git branch -a

# 查看远程分支
git branch -r

# 查看分支,以及每个分支最新的提交
git branch -v

# 查看已经合并到当前分支的分支
git branch --merged

# 查看还没有合并到当前分支的分支
git branch --no-merged

2. 创建和切换分支

# 创建分支
git branch branchname

# 切换分支
git checkout branchname
# 或(Git 2.23+)
git switch branchname

# 创建并切换到新分支
git checkout -b branchname
# 或
git switch -c branchname

# 基于某个提交,创建分支
git checkout -b branchname commit_id

# 基于某个远程分支,创建本地分支
git checkout -b branchname origin/branchname

3. 合并分支

# 把指定分支,合并到当前分支
git merge branchname

# 合并时,禁用快进(fast-forward),生成一个合并提交
git merge --no-ff branchname

# 合并时,只快进(如果不能快进,就失败)
git merge --ff-only branchname

# 合并时,遇到冲突,中止合并
git merge --abort

# 合并时,保留合并的提交信息
git merge --no-edit branchname

4. 变基(rebase)

变基,是另一种合并分支的方式。它,会把当前分支的提交,"重新播放"到目标分支上,让提交历史,变成一条直线,更加整洁。

# 把当前分支,变基到目标分支
git rebase target_branch

# 交互式变基,可以修改、合并、删除、重新排序提交
git rebase -i target_branch

# 变基时,遇到冲突,解决冲突后,继续变基
git rebase --continue

# 变基时,遇到冲突,跳过当前提交
git rebase --skip

# 中止变基,恢复到变基前的状态
git rebase --abort

注意:变基,会修改提交历史。如果,你的分支,已经推送到了远程仓库,并且,有其他人基于这个分支开发,就不要使用变基,否则,会给其他人带来麻烦。变基,只适合在本地分支,或者,只有你一个人使用的分支上使用。

5. 删除分支

# 删除本地分支(已经合并的)
git branch -d branchname

# 强制删除本地分支(不管有没有合并)
git branch -D branchname

# 删除远程分支
git push origin --delete branchname
# 或
git push origin :branchname

6. 分支命名规范

良好的分支命名,能让团队协作,更加顺畅。常见的分支命名规范:

  • master / main:主分支,稳定版本,随时可以发布
  • develop:开发分支,集成所有开发中的功能
  • feature/xxx:功能分支,开发新功能
  • bugfix/xxx:bug修复分支,修复bug
  • hotfix/xxx:紧急修复分支,修复线上紧急bug
  • release/xxx:发布分支,准备发布新版本
  • experiment/xxx:实验分支,做技术实验

远程仓库

远程仓库,是托管在网络上的项目版本库,如GitHub、GitLab、Bitbucket、Gitee等。通过远程仓库,你可以和其他人,协作开发。

1. 查看远程仓库

# 查看远程仓库
git remote

# 查看远程仓库,以及对应的URL
git remote -v

# 查看远程仓库的详细信息
git remote show origin

2. 添加远程仓库

# 添加远程仓库
git remote add origin https://github.com/user/repo.git

# 修改远程仓库的URL
git remote set-url origin https://github.com/user/newrepo.git

# 重命名远程仓库
git remote rename oldname newname

# 删除远程仓库
git remote remove remotename

3. 抓取和拉取

# 从远程仓库,抓取所有分支的更新(不合并)
git fetch

# 从指定远程仓库,抓取更新
git fetch origin

# 从远程仓库,拉取更新(抓取+合并)
git pull

# 从指定远程仓库和分支,拉取更新
git pull origin branchname

# 拉取时,使用变基(而不是合并)
git pull --rebase

# 拉取所有远程分支
git pull --all

4. 推送

# 推送当前分支,到远程仓库
git push

# 推送指定分支,到远程仓库
git push origin branchname

# 第一次推送时,设置上游分支(以后可以直接git push)
git push -u origin branchname
# 或
git push --set-upstream origin branchname

# 推送所有分支
git push --all

# 推送标签
git push origin tagname

# 推送所有标签
git push --tags

# 强制推送(危险!会覆盖远程仓库的历史)
git push --force

# 更安全的强制推送(如果远程仓库,在你上次拉取后,有新的提交,就拒绝推送)
git push --force-with-lease

注意:git push --force,会覆盖远程仓库的历史,非常危险!如果,有其他人,基于远程仓库的分支开发,强制推送,会给其他人带来麻烦。除非,你确定,只有你一个人使用这个分支,否则,不要使用强制推送。

5. 远程分支操作

# 查看远程分支
git branch -r

# 创建本地分支,跟踪远程分支
git checkout -b localname origin/remotename

# 设置当前分支,跟踪指定远程分支
git branch -u origin/remotename

# 查看分支的跟踪关系
git branch -vv

# 删除远程分支
git push origin --delete branchname

# 清理远程仓库已经删除的分支引用
git remote prune origin

标签管理

标签,用于标记项目历史中的某个重要节点,通常是发布版本(如v1.0.0)。

1. 查看标签

# 查看所有标签
git tag

# 按模式筛选标签
git tag -l "v1.*"

# 查看标签的详细信息
git show v1.0.0

2. 创建标签

# 创建轻量标签(只是一个指向提交的指针)
git tag v1.0.0

# 创建附注标签(包含标签名、邮箱、日期、标签信息,推荐)
git tag -a v1.0.0 -m "版本1.0.0发布"

# 基于某个提交,创建标签
git tag -a v1.0.0 commit_id -m "版本1.0.0发布"

3. 推送标签

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

# 推送所有标签
git push --tags

4. 删除标签

# 删除本地标签
git tag -d v1.0.0

# 删除远程标签
git push origin --delete v1.0.0
# 或
git push origin :refs/tags/v1.0.0

常见工作流

1. Git Flow

Git Flow,是一种比较经典的分支管理工作流。它,定义了五种分支:

  • master:主分支,存储正式发布的版本
  • develop:开发分支,集成所有开发中的功能
  • feature/*:功能分支,从develop分支创建,开发完成后,合并回develop
  • release/*:发布分支,从develop分支创建,准备发布新版本,发布后,合并到master和develop
  • hotfix/*:紧急修复分支,从master分支创建,修复线上紧急bug,修复后,合并到master和develop

Git Flow,适合有明确版本发布周期的项目。但它,比较复杂,对于持续交付的项目,可能不太适合。

2. GitHub Flow

GitHub Flow,是一种更简单、更轻量的工作流。它,只有两种分支:

  • master:主分支,随时可以部署
  • feature/*:功能分支,从master分支创建,开发完成后,通过Pull Request,合并回master

GitHub Flow,适合持续部署、持续交付的项目。它,简单、灵活,是目前最流行的工作流之一。

3. GitLab Flow

GitLab Flow,是GitLab提出的工作流,结合了Git Flow和GitHub Flow的优点。它,在GitHub Flow的基础上,增加了环境分支(如pre-production、production),来管理不同环境的部署。

4. 个人开发工作流

对于个人开发,工作流,可以更简单:

  1. 在master分支,保持稳定
  2. 开发新功能时,创建feature分支
  3. 在feature分支,开发和提交
  4. 开发完成后,合并回master
  5. 推送master到远程仓库

常见问题和解决方法

1. 合并冲突

当两个人,同时修改了同一个文件的同一部分,合并时,就会产生冲突。

解决方法:

  1. git status,查看哪些文件有冲突
  2. 打开有冲突的文件,找到冲突标记(<<<<<<<=======>>>>>>>
  3. 手动修改文件,解决冲突,删除冲突标记
  4. git add,把修改后的文件,添加到暂存区
  5. git commit,完成合并

2. 提交了错误的内容

如果,你刚提交了错误的内容,还没有推送到远程仓库:

# 修改上一次提交(可以修改提交信息,或者添加遗漏的文件)
git commit --amend

# 或者,撤销上一次提交,保留修改在工作区
git reset --soft HEAD~1
# 然后,重新修改和提交

如果,已经推送到了远程仓库,不要使用git reset,而应该使用git revert,创建一个新的提交,来撤销之前的提交:

# 撤销指定提交
git revert commit_id

# 撤销最近一次提交
git revert HEAD

3. 不小心add了不该add的文件

# 把指定文件,从暂存区移除(保留在工作区)
git reset HEAD filename

# 或者(Git 2.23+)
git restore --staged filename

4. 不小心删除了文件

# 恢复工作区中,被误删的文件(恢复到暂存区的状态)
git checkout -- filename

# 或者(Git 2.23+)
git restore filename

# 如果,已经提交了删除,恢复到某个提交的版本
git checkout commit_id -- filename

5. 想查看某个历史版本的文件

# 查看某个提交的文件内容
git show commit_id:filename

# 把某个提交的文件,恢复到工作区
git checkout commit_id -- filename

6. 想撤销所有本地修改,恢复到远程仓库的状态

# 抓取远程仓库的最新内容
git fetch origin

# 强制重置本地分支,到远程分支的状态(危险!会丢弃所有本地修改)
git reset --hard origin/branchname

7. 提交信息写错了

# 修改上一次提交的提交信息
git commit --amend -m "新的提交信息"

# 如果,已经推送到远程仓库,需要强制推送(谨慎!)
git push --force-with-lease

8. 想把一个分支的某个提交,应用到另一个分支

# 切换到目标分支
git checkout target_branch

# 把指定提交,应用到当前分支
git cherry-pick commit_id

# 应用多个提交
git cherry-pick commit1 commit2 commit3

# 应用一个范围的提交
git cherry-pick commit1..commit2

Git最佳实践

  1. 频繁提交,每次提交,只做一件事:不要攒一大堆修改,才提交一次。每次提交,应该只包含一个逻辑上的修改,这样,历史更清晰,也更容易回滚。
  1. 写好提交信息:提交信息,应该简洁明了,说明这次提交,做了什么。推荐的格式:第一行,简短描述(不超过50字符);空一行;详细描述(可选)。
  1. 使用分支:不要直接在master分支上开发。开发新功能、修复bug,都应该创建单独的分支。
  1. 定期拉取远程更新:在开始工作前,先git pull,拉取远程仓库的最新更新,避免冲突。
  1. 提交前,先检查修改:提交前,用git diff,检查一下自己的修改,确保没有提交错误的内容(如调试代码、密码、密钥等)。
  1. 不要提交敏感信息:不要把密码、密钥、配置文件等敏感信息,提交到Git仓库。可以使用.gitignore,忽略这些文件,或者使用环境变量。
  1. 不要提交大文件和编译产物:不要把大文件(如视频、安装包)、编译产物(如node_modules、dist、bin)、日志文件等,提交到Git仓库。使用.gitignore,忽略这些文件。
  1. 使用.gitignore:在项目开始时,就创建好.gitignore文件,忽略不需要版本控制的文件。
  1. 变基 vs 合并:本地分支,或者只有你一个人使用的分支,可以使用变基,让历史更整洁;共享分支,使用合并,不要修改历史。
  1. 推送前,先测试:推送代码到远程仓库前,先在本地测试,确保代码能正常运行,不要把有问题的代码,推上去。
  1. 使用Pull Request / Merge Request:团队协作时,通过Pull Request(GitHub)或Merge Request(GitLab),来合并代码。这样,可以进行代码审查,讨论修改,确保代码质量。
  1. 定期清理分支:合并后的分支,及时删除,保持分支列表整洁。

学习资源

推荐书籍

  • 《Pro Git》:Git官方书籍,深入浅出,非常适合学习Git。有中文版,免费在线阅读:https://git-scm.com/book/zh/v2
  • 《Git权威指南》:国内作者写的Git书籍,非常详细,适合深入学习。

在线教程

  • Git官方文档:https://git-scm.com/doc
  • GitHub Guides:https://guides.github.com/
  • 廖雪峰的Git教程:https://www.liaoxuefeng.com/wiki/896043488029600
  • 菜鸟教程Git教程:https://www.runoob.com/git/git-tutorial.html

交互式学习

  • Learn Git Branching:https://learngitbranching.js.org/ ,通过可视化的方式,交互式学习Git分支,非常有趣,也非常有效。
  • Git Immersion:https://gitimmersion.com/ ,通过实际操作,学习Git。

总结

Git版本控制要点:

  1. 什么是版本控制:记录文件内容变化以便查阅特定版本的系统,解决复制文件夹管理版本的原始方式的问题(版本混乱、查找困难、协作冲突、占用空间)。分为集中式(SVN/CVS,所有版本数据在中央服务器,必须联网,服务器挂了所有人无法工作,数据丢了所有版本丢了)和分布式(Git/Mercurial,每个开发者电脑都有完整版本库,离线能工作,安全性高,分支合并强大灵活)。
  2. Git基本原理:记录快照不是差异(每次提交保存所有文件状态快照,未修改文件保留链接指向之前相同文件,让分支合并非常高效);三个区域(工作区Working Directory是电脑里能看到的项目目录,暂存区Staging Area/Index是.git/index保存下次提交的文件列表,版本库Repository是.git目录保存所有版本数据);工作流程(工作区修改文件→git add添加到暂存区→git commit提交到版本库形成新版本);四种对象(blob存储文件内容,tree存储目录结构,commit存储提交信息作者时间提交信息tree哈希父提交哈希,tag指向某个commit),用SHA-1哈希值标识每个对象;引用(branch分支指向commit的指针提交时自动前移,tag标签指向commit通常不移动用于标记重要版本,HEAD指向当前所在分支的指针)。
  3. 基本命令:配置(git config --global user.name/user.email/core.editor/core.autocrlf,git config --list查看);创建仓库(git init初始化,git clone克隆);查看状态(git status,-s简洁模式);添加到暂存区(git add filename,git add .所有修改新增,git add -A所有修改新增删除,-i交互式,-p补丁模式逐块选择);提交(git commit,-m指定信息,-a提交所有已跟踪文件修改不需先add,--amend修改上一次提交);查看历史(git log,--oneline简洁一行,-n最近N次,-p显示差异,--stat统计信息,--graph --oneline --all图形化分支合并,--author按作者,--since/--until按时间,filename某个文件,--follow包括被重命名文件);查看差异(git diff工作区和暂存区,--cached/--staged暂存区和版本库,HEAD工作区和版本库,commit1 commit2两个提交,branch1 branch2两个分支,filename某个文件,--stat统计行数);撤销操作(git checkout -- filename/ git restore filename撤销工作区修改恢复到暂存区,git reset HEAD filename/ git restore --staged filename撤销暂存区添加放回工作区,git checkout HEAD -- filename/ git restore --source=HEAD --staged --worktree filename撤销工作区和暂存区恢复到最近提交,git reset --soft HEAD~1撤销最近提交保留修改在工作区,git reset --mixed HEAD~1/ git reset HEAD~1撤销最近提交保留修改在暂存区,git reset --hard HEAD~1撤销最近提交丢弃修改危险,git reset --hard commitid撤销到某个提交丢弃之后所有提交危险,注意git reset --hard会丢弃工作区暂存区修改非常危险使用前确认不需要修改);删除移动(git rm filename删除并添加到暂存区,--cached只从Git移除跟踪保留在工作区,git mv oldname newname重命名移动并添加到暂存区);忽略文件(.gitignore指定要忽略的文件,.log所有log文件,nodemodules/忽略目录,/dist忽略根目录dist,!取反,doc/.txt忽略doc目录下txt不包括子目录,doc/*/.pdf忽略doc目录所有pdf包括子目录,GitHub提供常用.gitignore模板库github.com/github/gitignore)。
  4. 分支管理:查看分支(git branch本地,-a所有包括远程,-r远程,-v每个分支最新提交,--merged已经合并到当前分支,--no-merged还没合并);创建切换(git branch branchname创建,git checkout branchname/ git switch branchname切换,git checkout -b branchname/ git switch -c branchname创建并切换,基于某个提交git checkout -b branchname commitid,基于远程分支git checkout -b branchname origin/branchname);合并(git merge branchname把指定分支合并到当前,--no-ff禁用快进生成合并提交,--ff-only只快进不能快进就失败,--abort遇到冲突中止合并,--no-edit保留合并提交信息);变基rebase(git rebase targetbranch把当前分支变基到目标分支,-i交互式变基可以修改合并删除重新排序提交,--continue解决冲突后继续,--skip跳过当前提交,--abort中止恢复到变基前,注意变基会修改提交历史,已经推送到远程且有其他人基于这个分支开发不要使用变基,只适合本地分支或只有你一个人使用的分支);删除分支(git branch -d branchname删除已合并的本地分支,-D强制删除不管有没有合并,git push origin --delete branchname/ git push origin :branchname删除远程分支);分支命名规范(master/main主分支稳定版本随时发布,develop开发分支集成开发功能,feature/xxx功能分支,bugfix/xxx bug修复分支,hotfix/xxx紧急修复分支,release/xxx发布分支,experiment/xxx实验分支)。
  5. 远程仓库:查看(git remote,-v对应URL,show origin详细信息);添加(git remote add origin URL,set-url修改URL,rename重命名,remove删除);抓取拉取(git fetch抓取所有分支更新不合并,git fetch origin指定远程,git pull拉取更新抓取+合并,git pull origin branchname指定远程分支,--rebase拉取时使用变基,--all拉取所有远程分支);推送(git push推送当前分支,git push origin branchname指定分支,-u/--set-upstream第一次推送设置上游分支以后可直接git push,--all推送所有分支,git push origin tagname推送指定标签,--tags推送所有标签,--force强制推送危险会覆盖远程历史,--force-with-lease更安全的强制推送如果远程在你上次拉取后有新提交就拒绝,注意git push --force会覆盖远程历史非常危险除非确定只有你一个人使用否则不要用);远程分支操作(git branch -r查看远程分支,git checkout -b localname origin/remotename创建本地分支跟踪远程,git branch -u origin/remotename设置当前分支跟踪指定远程,git branch -vv查看分支跟踪关系,git push origin --delete branchname删除远程分支,git remote prune origin清理远程已删除的分支引用)。
  6. 标签管理:查看(git tag,-l "v1.*"按模式筛选,git show v1.0.0查看详细信息);创建(git tag v1.0.0轻量标签只是指向提交的指针,git tag -a v1.0.0 -m "信息"附注标签包含标签名邮箱日期信息推荐,基于某个提交git tag -a v1.0.0 commit_id -m "信息");推送(git push origin v1.0.0推送指定标签,--tags推送所有标签);删除(git tag -d v1.0.0删除本地标签,git push origin --delete v1.0.0/ git push origin :refs/tags/v1.0.0删除远程标签)。
  7. 常见工作流:Git Flow(五种分支master主分支正式发布版本,develop开发分支集成开发功能,feature/从develop创建开发完成合并回develop,release/从develop创建准备发布发布后合并到master和develop,hotfix/从master创建修复线上紧急bug修复后合并到master和develop,适合有明确版本发布周期的项目但比较复杂);GitHub Flow(两种分支master主分支随时可部署,feature/从master创建开发完成通过Pull Request合并回master,简单灵活适合持续部署持续交付是目前最流行的工作流之一);GitLab Flow(结合Git Flow和GitHub Flow优点,增加环境分支如pre-production production管理不同环境部署);个人开发工作流(master保持稳定,开发新功能创建feature分支,开发提交,完成合并回master,推送到远程)。
  8. 常见问题解决:合并冲突(git status查看冲突文件,打开文件找冲突标记<<<<<<< ======= >>>>>>>,手动修改解决冲突删除标记,git add添加到暂存区,git commit完成合并);提交错误内容(还没推送git commit --amend修改上一次提交或git reset --soft HEAD~1撤销保留修改在工作区重新修改提交;已经推送不要用git reset应该用git revert commitid创建新提交撤销之前的提交,git revert HEAD撤销最近一次);不小心add了不该add的文件(git reset HEAD filename/ git restore --staged filename从暂存区移除保留在工作区);不小心删除文件(git checkout -- filename/ git restore filename恢复工作区误删文件恢复到暂存区状态;已经提交了删除git checkout commitid -- filename恢复到某个提交的版本);查看某个历史版本的文件(git show commitid:filename查看内容,git checkout commitid -- filename恢复到工作区);撤销所有本地修改恢复到远程(git fetch origin抓取最新,git reset --hard origin/branchname强制重置本地分支到远程状态危险会丢弃所有本地修改);提交信息写错了(git commit --amend -m "新信息"修改上一次提交信息,已经推送需要git push --force-with-lease谨慎);把一个分支某个提交应用到另一个分支(git checkout targetbranch切换到目标分支,git cherry-pick commitid应用指定提交,多个提交git cherry-pick commit1 commit2,范围git cherry-pick commit1..commit2)。
  9. 最佳实践:频繁提交每次只做一件事(不要攒一大堆修改才提交,每次提交只包含一个逻辑修改历史更清晰更容易回滚);写好提交信息(简洁明了说明做了什么,第一行简短描述不超过50字符空一行详细描述可选);使用分支(不要直接在master开发,新功能修复bug创建单独分支);定期拉取远程更新(开始工作前先git pull避免冲突);提交前先检查修改(git diff检查确保没有提交错误内容如调试代码密码密钥);不要提交敏感信息(密码密钥配置文件等用.gitignore忽略或环境变量);不要提交大文件和编译产物(视频安装包node_modules dist bin日志等用.gitignore忽略);使用.gitignore(项目开始就创建好);变基vs合并(本地分支或只有你一个人用的分支可以变基让历史整洁,共享分支用合并不修改历史);推送前先测试(本地测试确保正常运行不要推有问题的代码);使用Pull Request/Merge Request(团队协作通过PR/MR合并代码进行代码审查讨论修改确保质量);定期清理分支(合并后的分支及时删除保持列表整洁)。
  10. 学习资源:《Pro Git》Git官方书籍深入浅出有中文版免费在线阅读git-scm.com/book/zh/v2,《Git权威指南》国内作者写的非常详细;在线教程Git官方文档git-scm.com/doc,GitHub Guides guides.github.com,廖雪峰Git教程,菜鸟教程Git教程;交互式学习Learn Git Branching learngitbranching.js.org可视化交互式学习分支非常有趣有效,Git Immersion gitimmersion.com通过实际操作学习。

Git,是目前世界上,最流行、最强大的分布式版本控制系统。对于程序员来说,Git,已经成为了必备技能。掌握了Git,你就能更好地管理代码版本,追踪代码变更,进行团队协作。

学习Git,不要死记硬背命令,而要理解它的基本原理。理解了Git的三个区域、对象、引用、分支等基本概念,很多命令,就自然而然地理解了,不需要死记硬背。

另外,学习Git,最好的方式,就是多实践。在实际项目中,多使用Git,遇到问题,多查文档,多尝试,慢慢就熟练了。

"工欲善其事,必先利其器。"希望这篇文章,能帮你掌握Git这个强大的工具,让你的开发工作,更加高效、更加顺畅。

最后,记住:Git,只是工具。好的工具,能提升效率,但真正决定项目质量的,还是代码本身和团队协作。 不要过度追求工具的技巧,而忽略了代码质量和团队沟通。

祝你,在Git的世界里,游刃有余,高效协作!