Git 操作

练习地址:https://learngitbranching.js.org/

提交/回退

commit

git add .
git commit -m "修改了 xxx"
git commit --amend -m "fix: 还修改了 xxx"

amend 参数可以修改上一条 commit 信息,不会产生新的 commit

log

# 查看 commit 日志
git log

# 查看 commit 日志,每行显示一条
git log --oneline

# 查看 commit 日志,以图表形式显示
git log --graph

# 查看所有分支的 commit 日志
git log --all

reset

reset 针对的是本地仓库,不会影响远程仓库 reset 的目标指的是回退“到”哪条 commit,而不是将某条 commit 作废

# 回退到上一条 commit,不删除工作区的修改
git reset --soft HEAD~1

# 回退到上一条 commit,并删除工作区的修改
git reset --mixed HEAD~1

# 回退到上一条 commit,并删除工作区和暂存区的修改
git reset --hard HEAD~1

revert

revert 与 reset 的区别在于 revert 会产生一条新的 commit 来作废某条 commit 这样的作用是当将代码提交到远程仓库后,可以使用 revert 来回退 revert 的目标指的是回退哪条 commit (即把它作废),而不是回退到某条 commit

# 回退到上一条 commit,相当于把 HEAD 的修改作废
git revert HEAD

# 回退到上两条 commit
git revert HEAD~2

.gitignore

# 忽略文件
*.log

# 忽略文件夹
/node_modules

# 忽略文件夹下的所有文件
/dist/*

# 忽略所有文件夹
/*
# 问号通配符,匹配任意一个字符
*.log?

# 排除指定文件
!dist/index.html

git stash

# 暂存工作区的修改
git stash

# 查看暂存的工作区修改
git stash list

# 应用暂存的工作区修改,不删除暂存
git stash apply

# 恢复暂存的工作区修改,并删除暂存
git stash pop

# 删除暂存的工作区修改
git stash drop

# 删除暂存的工作区修改,并丢弃
git stash clear

分支

新建分支

git branch <branch-name>

删除分支

git branch -d <branch-name>

HEAD

HEAD 是当前分支的指针,指向当前分支的最新 commit git checkout 可以移动 HEAD 指针到指定分支

分支移动

# 移动分支到指定 commit
git branch -f <branch-name> <commit-id>

相对引用

# 移动分支到指定 commit 的上 1 个 commit
git branch -f <branch-name> HEAD~1

# 移动分支到指定 commit 的上 2 个 commit
git branch -f <branch-name> HEAD~2

# 移动分支到指定 commit 的父 commit
git branch -f <branch-name> HEAD^

# 移动分支到指定 commit 的父 commit 的上 2 个commit
git branch -f <branch-name> HEAD^~2

差异

在 Git 中,可以通过多种方式查看两个分支之间的不同之处。以下是常见方法及其用途:


1. 使用 git diff 查看分支之间的内容差异 git diff 是最直接的方法,用于比较两个分支的代码内容差异。

命令格式

git diff <branch1> <branch2>

说明

示例

git diff main feature

带文件名的差异(简化输出)

git diff --name-only main feature

比较目录结构差异

git diff --stat main feature

2. 使用 git log 查看提交历史差异 git log 用于比较两个分支的提交历史。

命令格式

git log <branch1>..<branch2>

说明

示例

git log main..feature

可视化提交差异

git log --oneline --graph main feature

3. 使用 git diff 比较工作目录与分支差异 如果你需要比较当前分支的状态(包括工作目录中的未提交更改)和另一分支的状态,可以运行:

git diff HEAD <branch>

4. 使用 git cherry 查看特有提交 git cherry 是专门用来比较分支间特有提交的工具。

命令格式

git cherry <branch1> <branch2>

说明

示例

git cherry main feature

5. 使用图形化命令查看分支差异 git log --graph

git log --graph --oneline --all --decorate

分支合并基础点

git merge-base <branch1> <branch2>

6. 使用图形化工具 如果你希望更直观地查看分支之间的差异,可以使用以下工具:

合并

rebase 与 merge 的区别在于 rebase 不会产生新的 commit,而是将当前分支的修改,应用到指定分支的后面 而 merge 会将当前分支的修改,与指定分支的修改合并,形成一个新的 commit

rebase

# 将当前分支的修改,合并到指定分支
git rebase <branch-name>
# 等同于
git rebase <branch-name> HEAD

# 将分支 B 的修改,合并到分支 A
git rebase <branch-A> <branch-B>

交互式 rebase

# 交互式 rebase,可以调整 commit 的顺序,选择哪些 commit 需要 rebase
git rebase -i <branch-name>

执行 git rebase -i(交互式变基)后,Git 会打开一个文本编辑器(如 vim 或你系统配置的默认编辑器),允许你按照自己的需求对提交历史进行修改。这是一个非常灵活的工具,用于清理提交历史、修改提交信息或合并多个提交。


1. 基本流程 执行命令

git rebase -i <base>

2. 编辑器界面 Git 会打开一个文本编辑器,显示一个提交列表,格式如下:

pick 1234567 First commit message
pick 89abcde Second commit message
pick fedcba9 Third commit message

每一行的含义


3. 可用指令 你可以修改第一列的指令,Git 会根据这些指令执行相应操作。常用的指令包括:

指令 作用
pick 保留提交,不做任何更改(默认行为)。
reword 修改提交的描述信息(提交内容保持不变)。
edit 停止在该提交点,允许你修改提交的内容(手动 amend 或其他操作后继续)。
squash 将当前提交与前一个提交合并,允许修改合并后的提交信息。
fixup 类似 squash,但直接丢弃合并后的提交信息,只保留前一个提交的信息。
drop 删除提交(该提交将从历史中完全移除)。

4. 修改示例 假设你在变基时看到以下提交:

pick 1234567 Add feature A
pick 89abcde Fix bug in feature A
pick fedcba9 Add tests for feature A

示例操作:

  1. 修改提交信息
  2. 合并提交
  3. 删除提交

5. 常见操作后续指令 继续变基 完成指定操作后,运行:

git rebase --continue

解决冲突 如果过程中发生冲突:

  1. Git 会提示冲突文件:
    CONFLICT (content): Merge conflict in <file>
    
  2. 手动解决冲突并标记已解决:
    git add <file>
    
  3. 继续变基:
    git rebase --continue
    

放弃变基 如果中途不想继续变基,可以运行:

git rebase --abort

6. 使用场景

通过 git rebase -i,你可以按需调整提交历史,确保代码库的提交记录更清晰、更简洁,便于团队协作和代码审查。

merge

# 将指定分支的修改,合并到当前分支
git merge <branch-name>

cherry-pick

# 将指定分支的多个指定 commit,合并到当前分支
git cherry-pick <commit-id1> <commit-id2> ..

标签

tag

# 创建标签
git tag <tag-name> <commit-id>

describe

# 查看离当前 commit 最近的标签及 commit 数量
git describe
# 返回如 v1.0.0-2-g1234567,表示当前 commit 比标签 v1.0.0 多 2 个 commit,且 commit id 为 1234567

# 查看指定 commit 的标签
git describe <commit-id>

远程分支

clone

# 克隆远程仓库
git clone <remote-repo-url>

# 克隆远程仓库到指定目录
git clone <remote-repo-url> <local-dir>

fetch

# 从远程仓库拉取最新数据
git fetch <remote-repo-url>

# 从远程仓库拉取最新数据到指定分支
# 如果本地没有该分支,则自动创建
git fetch <remote-repo-url> <branch-name>

pull

# 从远程仓库拉取最新数据,并合并到当前分支
git pull <remote-repo-url>

# 从远程仓库拉取最新数据,并合并到指定分支
# 如果本地没有该分支,则自动创建
git pull <remote-repo-url> <branch-name>

push

# 将本地分支的修改,推送到远程仓库
# 如果远程没有该分支,则自动创建
git push <remote-repo-url> <branch-name>

# 删除远程分支
git push <remote-repo-url> :<branch-name>

最佳实践

pull request

github 为了保证代码质量,要求所有代码提交必须通过 pull request 审核后才能合并到主干分支。 操作如下:

# 创建一个 feature 分支
# 完成开发后,合并到 develop 分支
# 在 github 上创建 pull request,关联 develop 分支
# 审核通过后,合并到 master 分支

git flow

Git Flow 简介

Git Flow 是一种基于 Git 的分支管理模型,由 Vincent Driessen 提出,旨在为软件开发团队提供一个清晰的流程来管理代码版本控制和发布。

它定义了一组规范的分支策略和操作流程,适用于具有明确版本发布周期的项目,尤其是需要频繁发布版本的团队。


1. Git Flow 的核心概念

1.1 核心分支

Git Flow 定义了以下几类长期分支和临时分支:

  1. 主分支 (master)
  2. 开发分支 (develop)

1.2 辅助分支 辅助分支用于完成特定任务,如开发新功能、修复 Bug 或准备版本发布。常见有以下三类:

  1. 功能分支 (feature)
  2. 发布分支 (release)
  3. 热修复分支 (hotfix)

2. Git Flow 的工作流程

2.1 日常开发

  1. develop 分支创建一个功能分支:
    git checkout develop
    git checkout -b feature/<功能名>
    
  2. 开发完成后,将功能分支合并回 develop
    git checkout develop
    git merge feature/<功能名>
    git branch -d feature/<功能名>
    

2.2 准备发布

  1. 创建一个 release 分支:
    git checkout develop
    git checkout -b release/<版本号>
    
  2. 修复 Bug 和更新文档。
  3. 将发布分支合并到 masterdevelop
    git checkout master
    git merge release/<版本号>
    git checkout develop
    git merge release/<版本号>
    git branch -d release/<版本号>
    
  4. 打标签:
    git tag -a <版本号> -m "Release <版本号>"
    

2.3 修复紧急问题

  1. master 创建一个热修复分支:
    git checkout master
    git checkout -b hotfix/<问题名>
    
  2. 修复问题并合并到 masterdevelop
    git checkout master
    git merge hotfix/<问题名>
    git checkout develop
    git merge hotfix/<问题名>
    git branch -d hotfix/<问题名>
    

3. Git Flow 的优点

  1. 清晰的分支结构:长期分支和短期分支分工明确,适合多人协作。
  2. 支持频繁发布:发布分支和热修复分支让版本管理更加规范。
  3. 版本历史清晰:不同分支记录了不同类型的改动(如新功能、Bug 修复、发布准备等)。

4. Git Flow 的局限性

  1. 不适合持续交付:Git Flow 假定版本发布有明确的周期,而不是随时发布。
  2. 分支较多:复杂的分支模型可能对新手或小团队造成负担。
  3. 在快速迭代项目中显得笨重:例如,短期项目可能不需要严格的分支管理。

5. 工具支持


6. 适用场景 Git Flow 非常适合以下场景:

  1. 大型团队合作:多人协作需要清晰的分支管理。
  2. 明确的发布周期:如传统的软件开发或定期发布的项目。
  3. 需要严格版本控制:尤其是有多个生产版本同时维护的项目。

对于需要频繁、快速发布的小型项目,可以考虑使用更简单的分支模型(如 GitHub Flow 或 trunk-based development)。