跳转至

Git & GitHub

什么是 Git?

分布式版本控制系统 - 分布式:不需要联网,在自己的机器上就可以使用 - 版本控制:记录、管理、回溯文件的修改历史

Git 的三个区:工作区、暂存区和版本库

配置 Git

命令:git init

创建一个本地的 Git 版本库(使用当前目录作为 Git 仓库)

Git 基础用法

命令:git add .

将文件添加到暂存区

. 表示全部文件 当然,也可以将指定的文件加到暂存区 git add file_name

特点:只会添加修改过的文件

命令:git status

查看当前工作区和暂存区的状态

三种状态:

未跟踪 Untracked 已跟踪 Tracked 忽略 Ignored

命令:git commit -m "message"

提交更改

  • 不使用 -m 选项:打开编辑器,输入提交信息,-m 适合简短的信息,方便

命令:git log

查看所有提交历史

常用选项:

--oneline:以每一个提交占一行的形式显示 --graph:显示分支结构 --stat:显示文件修改信息 -p:显示详细的修改内容 注:一个短划线表示简写,两个短划线表示全称

有关"branch"的命令

git branch branch_name # 基于当前 HEAD 指向创建一个分支

git branch # 查看分支
git show-branch # 更详细

git checkout branch_name # 切换分支
git checkout -b branch_name # 先创建一个分支,再切换到该分支

git diff branch_name1 branch_name2 # 比较两个分支
git diff branch_name # 比较工作区和xx分支
git diff # 比较工作区和暂存区

有关"merge"的命令

git merge branch_name1 branch_name2 # 将多个分支的更改都合并到当前分支
三种 merge 情况

already up-to-date:当前分支 比 被合并分支 多提交 --- nothing changes fast-forward:被合并分支 比 当前分支 多提交 --- HEAD 将指向被合并分支 merge commit:当前分支和被合并分支都有新的提交,且修改了同一处内容,即遇到冲突,需要手动解决冲突

merge 操作一般都在 GitHub 上通过 pull request 完成,此时,自己之前的提交信息其实是没必要的,log 信息很乱,反而会有干扰,因此我们可以使用squash merge 或 rebase 在提交前处理自己之前的各种 log 信息。

git merge --squash  branch_name# 将相较于 branch_name 分支多出来的所有 commit 信息合并成一个commit,再 merge 到目标分支

如果有多个程序员同时开发一个项目,那么在代码历史树上将会有多个 branch 和 主 branch 交织在一起,而 rebase 不会出现多个分支交织的显示,rebase 永远都是一条线。

命令:git reset xxxx

读档,回到之前某一提交的状态

常用选项:

--soft:只修改 HEAD 指针 --mixed:默认选项,只修改 HEAD 指针和暂存区 --hard:全部修改,完全回退

关于 commit message

意义:记录更改的原因/内容,方便定位/回溯

Angular 规范: https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-format

<type>(<scope>): <short summary>
  │       │             │
  │       │             └─⫸ Summary in present tense. Not capitalized. No period at the end.
  │       │
  │       └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
  │                          elements|forms|http|language-service|localize|platform-browser|
  │                          platform-browser-dynamic|platform-server|router|service-worker|
  │                          upgrade|zone.js|packaging|changelog|docs-infra|migrations|
  │                          devtools
  │
  └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test

type:更改类型 scope:影响范围 summary:更改的简要描述 body:详细描述 footer:标签

BREAKING CHANGE: <breaking change summary>
<BLANK LINE>
<breaking change description + migration instructions>
<BLANK LINE>
<BLANK LINE>
Fixes #<issue number>

删除文件的两种情况

  • 删除暂存区文件,但保留工作区的文件:git rm --cached

如果想把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 --cached 选项即可:

  • 同时删除本地和版本库的文件:git rm

    若要修改远程仓库,即 GitHub 中的文件,还需要`git commit -m "delete xxx"

HEAD 指向的分支就是当前分支

.gitignore

规定忽略哪些文件 语法: - #:开头表示注释 - *:匹配一个或多个字符,**:匹配中间目录 - /:放在开头表示根目录

可以去网上找找常用语言的 .gitignore 模版

注意点

  • 合并分支时的注意点:假设要把 C 分支的代码合并到 A 分支,则必须先切换到 A 分支上,再运行 git merge 命令,来合并 C 分支!如果两个人修改的是一个文件的不同位置,在使用merge指令时,git 会自动帮我们合并,但若修改的是同一位置,此时会出现冲突!需要人为修改。
  • 删除分支时的注意点:删除分支不能在该分支上删除该分支
  • 不在分支没有被 pr(pull request) 之前 merge,最好少 commit,不然最后 merge 时非常困难,可以用rebase -i命令在本地压缩 commit 到一个里面
  • 在使用 git reset 的 hard 模式之前, 你需要再三确认选择的存档是不是你的真正目标. 如果你读入了一个较早的存档, 那么比这个存档新的所有记录都将被删除! 这意为着你不能随便回到"将来"了。

前面介绍的是自己一个人管理 github 仓库的流程,下面介绍多人协作的方法。

Github 工作流

git clone https://github.com/ultralytics/yolov5.git  # 克隆文件到本地

git checkout -b my_feature  # 创建并切换到新分支 效果:复制一份当前分支的内容到新分支上(现在有两个分支,其内容是一样的)

git diff  # 查看自己对代码的修改内容(相较于现在远程仓库现有内容)

git add 文件  # 把文件放到暂存区 让git知道我有一些代码想提交

git commit -m "提交信息"  # 将暂存取的内容提交到本地git,也就是让git管理

#以上是完成了本地管理

git push origin my_feature  # 将本地my_feature分支的内容push到github上 效果:github上多了一个my_feature分支

# 如果当push代码时发现,github仓库上main分支更新了,那么我就要测试在更新后,我更新的代码是否正确,因此,我现在需要将github更新后的内容同步到我的my_feature分支。
git checkout main  # 切换到本地的main分支,磁盘内容会发生修改

git pull origin main  # 把github上的现有分支main的内容(也就是上面说的main分支更新后的内容)拉取到本地

git checkout my_feature  # 此时磁盘内容有我自己修改的,但没有github上更新的

# rebase 自己的文件
git rebase main  # 同步这两个代码 效果:把我的修改先放在一边,然后把github上的修改拿过来,然后在此基础之上,再把我的修改加上去
# 在这个过程中,有可能会出现rebase conflict,就需要手动选择需要哪一个代码

git push -f origin my_feature  # -f force

# 上述步骤,我们将修改后的代码成功push到github上的my_feature分支,接着就需要等仓库的主人接受我们的分支,即我们提交pull request,请求仓库主任把我这个分支给pull到这个项目

# 仓库主人一般使用squash merge
# 效果:把这一个分支上的所有改变合并成一个改变,然后commit到main分支
# 然后再把远端的my_feature删掉,即delete branch

# 在我们本地,也应该把my_feature删掉
git checkout main

git branch -D my_feature # 删除my-feature分支

git pull origin master  # 再把远程的拉下来