git一般命令
git init # 创建一个git仓库
git status # 查看仓库当前状态变化
git diff # 查看较于上一次暂存都修改了哪些内容
git log # 查看日志
git log -l # 查看最后一次提交信息
如果一个仓库有多个分支,想要使用dev分支
git clone 地址
git branch -a 查看所有分支
git switch dev 切换到dev分支
git branch -a
fork一个仓库,clone后设置源代码为上游代码库
git clone git@github.com:{username}/mmengine.git
cd mmengine
git remote add upstream git@github.com:open-mmlab/mmengine.git
# 利用git remote -v 检查remote是否添加成功
# mmlab的提交前需要通过pre-commit审核
pre-commit run --all-files -c .pre-commit-config-zh-cn.yaml
# 审核通过后添加目标文件到暂存区,撰写commit后push
git add {目标文件} #
git commit -m "***"
git push -u origin {branch_name}
创建开发分支
# 保留master跟踪upstream的master分支,则创建自己开发的分支
git switch -c liuyoufu/dev
# 跟踪upstream的master
git pull upstream master
# 解决冲突
git fetch --all --prune
git rebase upstream/master
# 或
git fetch --all --prune
git merge upstream/master
关于git push出错问题
1、git push出错一般为账户未登录的错误
2、ssh与https认证不同,ssh通过设置ssh秘钥来完成证明;https通过develop->token获取github特定密码完成github在设备上的登录完成
取消暂存的文件/版本回退
# 提交后取消某个暂存文件
git add .
git status # 查看暂存区的状态 例如有两个文件:readme.md LICENSE.md
git reset HEAD readme.md # 撤销readme.md的修改
# 查找要回到commit的id
git reflog
git reset --hard {commit_id}
# 可以利用HEAD标识符 HEAD表示当前版本,HEAD^表示上一个版本
git reset --hard HEAD^
忽略文件提交配置
# 配置工作目录下的 .gitignore文件,若部分特殊不排除则用!
*.class
!App.class
# 强制添加被忽略文件
git add -f {文件}
删除文件
删除一个已经commit的文件
git add readme.md
git commit -m "add readme.md" # 提交修改
rm readme.md # 在文件管理器中删除readme.md文件
git status # 此时会报文件已删除 deleted: readme.md
# 如果确实要从版本库中删除此文件
git rm readme.md
git commit -m "remove readme.md"
# 如果要从版本库恢复文件 git checkout -- <file>
git checkout -- readme.md
分支管理
git 保存的不是文件变化或差异,而是一系列不同时刻的快照
假设一个工作目录下有三个要被暂存和提交的文件
git add readme.md test.md LICENSE
git commit -m "The initial commit of my project"
当进行提交操作时,git会先计算每一个子目录的校验和,然后在git仓库中这些校验和保存为树对象,随后,git便会创建一个提交对象,除了包含以上信息外,还包含指向这个树对象的指针。如此一来,git就可以在需要的时候重现此次保存的快照。
现在git仓库有五个对象:三个blob
对象(保存文件快照)、一个树对象(记录目录结构和blob对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息);
做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象的指针。
git的分支,其实本质上仅仅是指向提交对象的可变指针。git的默认分支名字是master,经过多次提交后,其实已经有一个指向最后那个提交对象的master分支,master分支每次提交时都会向前移动。
创建分支
git仓库都会有一个master分支,HEAD指向master指针,master指向最新一次commit;
每次提交master都会移动,当创建新的分支dev时,自动产生dev指针指向master想用的提交,再把HEAD指向dev,此时当前分支在dev上;此后的提交,dev的指针会移动,而master指针不变;
假如dev工作完成,把dev合并到master上:
方法:将master指针指向dev当前的分支
合并完成后,可以删除dev分支。
# 创建并指向dev分支
git switch -c dev # git checkout -b dev = git branch dev + git checkout dev
git branch # 查看当前分支
git add readme.md
git commit -m "branch test"
# dev分支工作完成后,切回到master
git switch master
# 把dev分支工作合并到master
git merge dev
# 删除dev分支
git branch -d dev
# 查看branch信息
git branch
分支管理
通常合并分支时,git会使用fast forward模型,这种模式下删除分支,会丢失分支信息;强制禁用fast forward模式,git会在merge产生一个新的commit,从分支历史上能看出分支信息。
git switch -c dev
git add readme.txt
git commit -m "add merge"
git switch master
git merge --no-f -m "merge with no-ff" dev
分支策略
分支管理基本原则:
1、master分支应该是非常稳定的,仅用来发布的版本,平时不用来干活
2、干活在dev分支,到某个时候再把dev分支合并到master上
bug分支
每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除;
模拟场景:上一个工作还为完成,已经add部分,但有master分支上有代号为issue-101的bug需要紧急修复
git status
# 将当前的工作现场储藏起来
git stash
git status # 此时工作区干净了
git switch master
git switch -c issue-101
# 开始修复
# 修复完毕
git add readme.md
git commit -m "fix bug"
git switch master
git merge --no-f -m "merged bug fix 101" issue-101
# 返回dev分支干活
git switch dev
git status
# 查看stash内容
git stash list
# 恢复stash内容的同时清空stash
git stash pop # git stash pop = git stash apply + git stash drop
# 把master上修复的bug merge到dev分支上 cherry-pick将相同改动赋给当前分支,然后创建新的commit
git branch
git cherry-pick <commit_id>
feature分支
添加新的功能
git switch -c feature-vulcan
# 创建新的分支并开发
# 开发完毕
git add vulcan.md
git commit -m "add feature vulcan"
git switch dev
git merge --no-f -m "add feature vulcan" feature-vulcan
# 若在尚未合并,删除分支
git branch -D feature-vulcan
解决冲突
将feature1分支merge到master上起冲突时
git switch master
git merge feature1
# 此时会报错fix conflicts
git status # 告诉哪个文件有冲突,并可接着查看冲突内容
# 修改后提交
git add readme.txt
git commit -m "confict fixed"
git cherry-pick
当只需要merge部分commit,使用cherry-pick
git cherry-pick <commit-hash-id A> <commit-hash-id B>
git多人协作
流程:
- 首先试图使用git push 推送自己的修改
- 推送失败,则git pull拉去合并
- 若有冲突,解决冲突
- 解决冲突后,git push
git clone <>
git remote # 查看远程库的信息
git remote -v # 显示更详细的信息
# 向origin推送master分支
git push origin master
git clone
git branch
git switch -c dev origin/dev # 创建远程origin的dev分支到本地dev分支
git add env.txt
git commit -m "add env"
git push origin dev # 向origin的dev分支推送
# 若出现合作者有相同的推送更改或者冲突,则先抓取,本地合并,然后解决冲突
git pull
# 若git pull失败,则可能本地dev与远程origin/dev分支没有建立链接
git branch --set-upstream-to=origin/dev dev
git pull
# 此时会有冲突产生,解决冲突再提交
git rebase
发布版本会在版本库中加上一个标签(tag),这是一个指向某个commit的指针。过多的提交会导致git log很乱,git有一种rebase操作,将分叉的提交变成直线,把本地未push的分叉提交历史整理成直线,目的是使得在查看历史提交的变化时更容易,因为分叉的提交需要三方对比
git log --graph --pretty=oneline --abbrev-commit
git rebase
git push
git 标签
如上述,发布一个版本就回在版本库上打一个标签,取某个标签就是把那个打标签的时刻的历史版本取出来,标签也是版本库的一个快照。
即将commit-hash-id 转为 一个好看的tag
git branch
git switch master
# 打一个标签 默认打在最新的commit上
git tag v1.0
# 查看所有标签 按字母顺序排序
git tag
# 若想在之前的commit添加tag
git log --pretty=oneline --abbrev-commit
git tag v0.9 <commit-hash-id>
# 查看标签信息
git show v0.9
# 创建带有说明的标签
git tag -a v0.1 -m "version 0.1 released" <commit-hash-id>
# 标签打错了可以删除
git tag -d v0.1
# 推送某个标签到远程
git push origin v1.0
# 推送所有标签到远程
git push origin --tags
# 完成标签推送后删除远程标签
git tag -d remove
git push origin :refs/tags/remove