git 工作流程
说明:
-
工作区就是创建仓库的文件夹如(
notebook
文件夹就是一个工作区) -
版本库就是工作区的隐藏目录.git,版本库中有暂存区(stage/index)和分支(master)
-
git add
实际是把文件添加到暂存区,git commit
把暂存区的内容提交到当前分支 -
创建新 git 仓库:
mkdir vu3.0-ui-dev
cd vu3.0-ui-dev
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/www-ly-cn/vu3.0-ui-dev.git
git push -u origin master
- 已有仓库
cd existing_git_repo
git remote add origin https://gitee.com/www-ly-cn/vu3.0-ui-dev.git
git push -u origin master
基本命令总结
基础配置
配置git永久保存账号密码,免去git重复输入账号密码操作
- 方法一
一般windows会在C盘的C:\Users\Administator(Linux在/home/用户名/)目录下生成 .gitconfig配置文件。用文档编辑工具打开该文件
添加:
[user]
name = wb-ly409739 //你的用户名
email = wb-ly409739@alibaba-inc.com //你的git邮箱账号
[credential]
helper = store
- 方法二
git config --global credential.helper store
- 基础配置
git config --global user.name "xxx"
git config --global user.email "xxx"
git config --global user.password "xxx" # 可不配置
# 记住用户名和密码
git config --global credential.helper store
# 别名
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.br branch
git config --global alias.psm 'push origin master'
git config --global alias.plm 'pull origin master'
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --"
git config --global core.editor "vim" # 设置Editor使用vim
git config --global color.ui true # 给 Git 着色
git config --global core.quotepath false # 设置显示中文文件名
- 通过命令的方式,查看设置的信息
git config --list
默认这些配置都在 ~/.gitconfig 文件下的,你可以找到这个文件查看自己的配置,也可以输入 git config -l 命令查看。
user.name=xxx
user.email=xxx
user.password=xxx
credential.helper=store
通过文件的方式,直接在家目录下查看设置的信息 /home/username
cat .gitconfig
[user]
name = xxx
email = xxx
password = xxx
[credential]
helper = store
- 使用 git config 命令用来配置 git 的配置文件,git配置级别主要有以下3类:
- 仓库级别 local 【优先级最高】git 仓库级别对应的配置文件是当前仓库下的 .git/config
- 用户级别 global【优先级次之】git 用户级别对应的配置文件是用户宿主目录【/home/username】下的~/.gitconfig 【宿主目录:C:\Users\username】
- 系统级别 system【优先级最低】git 系统级别对应的配置文件是git安装目录下的 /etc/gitconfig 【和git的安装位置有关】
配置文件的权重: 仓库>全局>系统
- 查看仓库配置【必须要进入到具体的目录下】
git config --local -l #-l/--list
- 查看用户配置
git config --global -l
- 查看系统配置
git config --system -l
- 查看所有的配置信息,依次是系统级别、用户级别、仓库级别
git config -l
- git config 常用配置选项
git config -e #编辑配置文件
git config --local -e #编辑仓库级别配置文件
git config --global -e #编辑用户级别配置文件
git config --system -e #编辑系统级别配置文件
- git config 添加配置项目
git config --global user.email “you@example.com”
git config --global user.name “Your Name”
- 删除配置项
git config --global|--local|--system --unset user.password
- 配置一些复杂命令的别名
git config --global alias.br branch # 接下来就可以直接使用 git br 命令了
常用的一个复杂命令的别名配置
# 查看项目分叉历史
git log --graph --all # 显示默认信息
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cd) %C(bold blue)<%an:%ae>%Creset' --abbrev-commit --date=iso-local # 定制化格式显示
# 配置别名 lol
git config --global alias.lol "log --graph --all" # 简单配置
# 配置可定制化的显示别名 lol
git config --global alias.lol "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cd) %C(bold blue)<%an:%ae>%Creset' --abbrev-commit --date=iso-local"
~ 与 ^
^
代表父提交,当一个提交有多个父提交时,可以通过在^
后面跟上一个数字,表示第几个父提交,^
相当于^1
.~<n>
相当于连续的<n>
个^
.checkout
只会移动HEAD
指针,reset
会改变HEAD
的引用值。
创建工作目录(git 管理形成本地仓库)
1、 创建 git 仓库文件夹(工作区)并进入到文件夹(工作区),名为: notebook
mkdir notebook && cd notebook
2、 初始化仓库 notebook
git init
3、 工作区添加 add
文件并暂存区,再 提交 commit
到仓库
# 创建文件并添加一些内容
echo "lean git" >> README.md
# 添加到仓库暂存区,在暂存区的文件,绿色标识
git add README.md (如果是 “.” 表示修改的文件全部添加到赞存区)
# 提交 README.md 文件到当前分支的仓库中, -m "提交说明"(只有进行 git add 后 git commit 命令才能提交到仓库,接下来才可以 通过 git push origin 分支名 提交到远程仓库中)
git commit -m "add README.md"
4、工作区修改文件
# 修改完成文件后,执行 git status 查看当前工作区中的文件状态,红色标识
git status
# 添加到仓库暂存区,并提交到当前分支(这里需要多次的添加到暂存区并提交到当前分支,因为需要不断的修改文件)
git add README.md
# 提交到当前分支的仓库中
git commit -m "modify README.md"
5、撤销修改文件(未提交到远程分支)
- 当文件在工作区时,执行撤销命令,使使文件返回到工作区
# 这个命令覆盖工作区的已修改的内容,要谨慎使用,否则你修改的一些内容全部付诸东流,个人一般不用,一般先 git add
git checkout -- README.md
- 当文件在暂存区时, 首先使文件回到工作区, 再执行撤销命令
# 使文件返回到暂存区,~ 一个表示上一次 commit 的版本,~~ 两个表示上上一次 commit 的版本,默认参数 --mixed,如: git reset --mixed HEAD^ README.md
git reset HEAD~ README.md
# 再执行撤销命令,使文件返回到工作区(谨慎使用,会覆盖当前工作去所有的修改)
git checkout -- README.md
版本控制 (reset无限次后悔)
在 Git 中,
HEAD
表示当前版本库,HEAD^
表示上一个版本库(commit 提交时的状态),HEAD^^
表示上一个的上一个版本库
1、查看提交的完整日志
git log [--graph]
2、查看提交的简要日志
git log --pretty=oneline
3、返回到上一个版本库
git reset --hard HEAD^
4、回到指定版本(hard 后面添加版本号 一般 7 位)
git reset --hard ae34256 # 或者分支名
5、查看命令历史
git reflog
远程仓库
这里需要在 github 上注册一下有才可继续接下来的学习......
- 在注册好的 github 上新建一个名为和本地名称一样的空的仓库
notebook
- 在本地工作空间
notebook
目录下执行如下命令:
# lyios8859-1 就是注册时的名称 (ssh和https的方式)
git remote add origin git@github.com:lyios8859-1/notebook.git [https://github.com/lyios8859-1/notebook.git]
- 把本地内容推送到 github 远程仓库上(第一次 push 必须带参数 -u 关联远程仓库)
git push -u origin master(master 可以是其他分支)
注意: 此时,如果报错, 证明电脑可能没有修改远程仓库的公钥
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
解决方法:
- 在 github 上点击头像下拉框的 Settings --> SSH and GPG keys --> new SSH key 添加 SHH 公钥
- 打开 id_rsa.pub 文件(windows 用户在 C:/Users/Administrator/.ssh/id.rsa.pub, Linux 用户在 root 在 /root/.ssh/ 下,普通用户是/home/您的用户名/.ssh/ 下。参考
- 将 id_rsa.pub 文件内容拷贝到 key 就可以了,title 任意。
克隆远程仓库到本地
# (ssh或https的方式)
git clone git@github.com:lyios8859-1/notebook.git [https://github.com/lyios8859-1/notebook.git]
- 拉取项目(从远程仓库更新本地仓库,前提是已关联)
git pull origin master (master 可以是其他分支)
分支(branch)
- 查看分支
git branch
- 创建分支
dev
git branch dev
- 切换当前需要工作的分支
dev
git checkout dev
PS: 这里有一个 HEAD
不断的改变会指向不同的分支
- 创建并切换到工作的分支
git checkout -b dev
- 合并某分支到当前分支
需求: 要把正在开发的分支 dev 的代码合并到 master 分支上, 前提 dev 分支是干净的, 都已经提交到版本库了, 没有任何的修改, 先切换到 master 分支上, 再执行合并操作
git merge dev
, 这样开发分支的代码就都合并到了 master 上了, 如果需要一个干净的 commit 提交操作,也可以使用git rebase
命令进行合并, 后面提到.
git merge dev
删除分支
- 普通方式删除(-d)
已经合并没做任何修改的分支
git branch -d xxx
- 强制删除(-D)
不管是否合,还是已经做了任何修改的分支
git branch -D xxx
- 查看分支合并的信息
git log --graph --pretty=oneline --abbrev-commit
藏匿当前未提交的分支
需求: 当前在修改自己的分支 dev,突然项目经理要求修复一个 bug
解决方法:
- 藏匿当前 dev 分支的工作状态
git stash
- 新建一个 bug-1(分支名任意) 分支
git branch -b bug-1
- 修复 bug 并提交,合并 bug-1 到 master 分支
git commit -m "fix the bug-1"
git checkout master
git merge --no-ff -m "merge bug-1" bug-1
- 删除 bug-1 分支
git branch -d bug-1
- 查看当前 stash
git stash list
- 恢复 dev 分支的工作状态,并删除 stash 内容
git stash pop # 暂存区代码还原并清除暂存区记录
暂存区代码还原,不会删除 stash 内容:
git stash apply
清空所有暂存区的记录:
git stash clear
drop 是只删除一条,当然后面可以跟 stash_id 参数来删除指定的某条记录,不跟参数就是删除最近的,而 clear 是清空。
团队协作(remote)
- 查看远程库信息
git remote
- 查看远程仓库详细信息
git remote -v
- 推送分支到远程仓库
git remote origin master
- 拉取远程分支到本地
git pull origin master
标签管理(tag)
- 创建一个标签,默认为
HEAD
当前分支添加标签
git tag v1.0
- 为版本号为
a6c3ed5
添加 v2.0 标签
git tag v2.0 a6c3ed5
- 为版本号为
23d23d4e
添加带有说明的标签,-a
指定标签名,-m
指定说明文字
git tag -a v3.0 -m "version 0.2 released" 23d23d4e
- 根据标签查看指定分支
git show v0.2
- 查看所有标签
git tag
- 删除 v1.0 标签
git tag -d v1.0
- 把 v0.9 标签推送到远程
git push origin v0.9
- 推送所有尚未推送到远程的本地标签
git push origin --tags
- 删除远程标签。先删除本地标签,再删除远程标签
git tag -d v0.9
git push origin :refs/tags/v0.9
git 的相关命令
git reset 回滚命令
git reset [--mixed | --soft | --hard] HEAD~
--mixed
: 默认参数,移动仓库中HEAD
的指向,将其指向上一个快照,将移动后指向的快照回滚到上一次commit
提交的暂存区,会回滚到暂存区。--soft
: 移动仓库中HEAD
的指向,将其指向上一个快照,不会回滚到暂存区--hard
: 移动仓库中HEAD
的指向,将其指向上一个快照,将移动后指向的快照回滚到上一次commit
提交的暂存区,会回滚到暂存区,而且还将暂存区的文件还原到工作目录中。
注意:如果使用命令 git reset --hard HEAD
,要谨慎,这样会对已经修改的文件内容也还原了。即修改的内容就不存在了。
回滚到某一次的 commit
, 通过 git log
或者 git log --oneline
获取到 hash 值,一般复制前 7 位即可
git log
git reset f81fca8e
git diff 文件对比命令
- 比较工作目录和本地仓库的某次
commit
的差异
# 比较工作目录和本地仓库的最后一次的 `commit` 的差异
git diff
#比较不同历史提的本地仓库的 `commit` 的差异
git diff f7b2a54 b1549f9
# 比较工作目录中的修改和 Git 本地仓库的 `commit` 的差异
git diff f7b2a54
- 比较暂存区和 Git 本地仓库的
commit
的差异
# 比较暂存区和本地仓库的最后一次的 `commit` 的差异
git diff --cached
# 比较暂存区与本地仓库的某次的 `commit` 的差异
git diff --cached f7b2a54
git rebase 命令
通俗讲:将当前分支设置为一个开始点(作为一个基线),这样就可以知道你当前分支于你需要比较的分支之间的差异。rebase 会把你当前分支的 commit 放到公共分支的最后面,所以叫变基。就好像你从公共分支又重新拉出来这个分支一样。
原理:rebase 需要基于一个分支来设置你当前的分支的基线,这基线就是当前分支的开始时间轴向后移动到最新的跟踪分支的最后面,这样你的当前分支就是最新的跟踪分支。这里的操作是基于文件事务处理的,所以你不用怕中间失败会影响文件的一致性。在中间的过程中你可以随时取消 rebase 事务。
注意:
- 不要在公共分支使用
rebase
- 本地和远端对应同一条分支,优先使用
rebase
, 而不是merge
- 打乱时间线
- commit 的提交会很干净,保证自己的提交都在一起,不会和别人的 commit 交叉在一起, 直接把自己所有的提交放在一起,合并到最前面
- 为什么不要再公共分支使用rebase?
因为往后提交的这些 commit
都是新的,这样其他从这个公共分支拉出去的人,都需要再 rebase
,相当于你 rebase
东西进来,就都是新的 commit
了
rebase 使用场景:
rebase
, 你自己开发分支一直在做,然后某一天,你想把主线的修改合到你的分支上,做一次集成,这种情况就用 rebase
比较好.把你的提交都放在主线修改的头上
- 常用指令选项
git rebase -I dev
可以将dev分支合并到当前分支, 这里的 -i
是指交互模式。就是说你可以干预rebase这个事务的过程,包括设置commit message,暂停commit等等。
git rebase –abort
放弃一次合并
- 合并多次commit操作:
git rebase -i dev
- 修改最后几次commit记录中的pick 为 squash
- 保存退出,弹出修改文件,修改 commit 记录再次保存退出(删除多余的 change-id 只保留一个 commit提交记录)
git add .
git rebase --continue
git merge 合并命令
注意:
- 不会打乱时间线
- commit 的提交会不干净,提交的历史记录和别人的提交交叉在一起
merge & rebase 区别
rebase 跟 merge 都是合并分支,区别是 merge 暴力合并,能知道代码来自哪个分支;rebase 比较合并,按代码的时间来给它重新排序,然后重新放置好,看起来很有逻辑,却不能得知哪个代码来自哪个分支。
几个有用的底层命令
工作区
- 对工作区的文件的修改撤销
git checkout -- filename # 这个命令很危险,会把已经修改的文件内容全部还原
暂存区
- 查看暂存区信息
git ls-files -s
# 100644 ed7ce12274bc71c66cb596feaaf9f02ce91b820e 0 test.txt
- 查看暂存区指定的修改的内容
git cat-file -p ed7ce12274bc71c66cb596feaaf9f02ce91b820e
- 撤销暂存区的修改(就是 git add filename 执行后,就会保存到暂存区)
git reset HEAD filename # git 低版本的使用
git restore --staged filename # git 高版本推荐
- 删除
git add filename
到暂存区的内容
git rm --cached filename # --cached 保留本地文件,或用 -f 强制删除
版本库(本地仓库)
- 修改最后一次 commit 提交的注释
git commit --amend
注意: 执行该命令之前先执行 git add filename
添加修改的内容到暂存区
查看所有命令操作的日志 reflog
git reflog
git log
只能查看 commit 的日志
删除未跟踪的文件
git clean -dn # 显示即将要删除未跟踪的文件
git clean -df # 删除未跟踪
git rm xxx
恢复已经通过命令 git add
到暂存区的修改,并且恢复到初始状态
- 方式一
# step 1: 从暂存区恢复到工作区
git reset xxx # xxx 表示需要恢复修改的某个文件
# step 2: 从工作区恢复即可,就可恢复初始状态
git checkout xxx # xxx 表示需要恢复修改的某个文件
- 方式二
# step 1: 从暂存区恢复到工作区
git restore --staged xxx # xxx 表示需要恢复修改的某个文件
# step 2: 从工作区恢复即可,就可恢复初始状态
git checkout xxx # xxx 表示需要恢复修改的某个文件
恢复已经通过命令 git commit
到版本库(本地仓库)的修改,并且恢复到初始状态
--soft
存在
# step 1: 从已经 commit 到版本库中恢复到暂存区
git reset --soft HEAD~1
# 此时查看状态:git status 暂存区存在修改没有 `git commit` 的文件
git status
# 此时查看日志: git log 已经没有刚 commit 的日志了
git log
# 此时查看暂存区的文件: git ls-files 还是存在的,接下来就从暂存区恢复到工作区
git ls-files
# step 2: 从暂存区恢复到工作区
git reset xxx # xxx 表示需要恢复修改的某个文件,就是之前 commit 的文件
# step 3: 从工作区恢复即可,就可恢复初始状态
git checkout xxx # xxx 表示需要恢复修改的某个文件,就是之前 commit 的文件
--soft
不存在
# step 1: 从已经 commit 到版本库中直接恢复到工作区
git reset HEAD~1
# 此时查看状态:git status 工作区存在修改没有 `git add` 的文件
git status
# 此时查看日志: git log 已经没有刚 commit 的日志了
git log
# 此时查看暂存区的文件: git ls-files 已经不存在了
git ls-files
# step 2: 从工作区恢复即可,就可恢复初始状态
git checkout xxx # xxx 表示需要恢复修改的某个文件,就是之前 commit 的文件
--soft:表示从版本库恢复到暂存区(删除了最新的提交并恢复到暂存区),如果没有该命令就会删除了最新的提交,直接恢复到工作区。
--hard
存在(谨慎使用该命令)
# step 1: 从已经 commit 到版本库中恢复到工作区的初始状态
git reset HEAD~1
# 此时查看状态:git status 已经没有任何修改文件了
git status
# 此时查看日志: git log 已经没有刚 commit 的日志了
git log
# 此时查看暂存区的文件: git ls-files 已经不存在了
git ls-files
提交分离的 HEAD 指向的更改(Committing detached HEAD Changes)
# 添加一个额外的功能,已经 commit 了,此时又想起需要 checkout 到某一次 commit 修改, 这样就会惨生 detached HEAD
git checkout 7698f1b6
# 此时 git log 会查看到 HEAD 指向某一个 commit 的 hash(这里指向 7698f1b6)
# commit 7698f1b6b8c931e8c2413b5c1e4e476d7a354d11 (HEAD)
git log
# 此时查看分支,会多一个分支,而且是 * 表示的当请工作分支
# 英文:* (HEAD detached at 7698f1b)
# 中文:* (头指针在 7698f1b 分离)
git branch
# 此时我们去修改任何的文件或添加文件
# 修改文件
echo "I forgot this part, good to have detached HEAD mode!" >> 2.txt
# 添加文件
touch detached-head.txt
# 此时查看状态,在 *(HEAD detached from 7698f1b6) 分支,有修改的 2.txt 文件和为跟踪的 detached-head.txt 文件
git status
# 在 detached HEAD 7698f1b6 分支,添加并提交
git add . && git commit -m "xxx"
# 在 detached HEAD 7698f1b6 分支,查看提交日志,HEAD 指向新的 commit hash
# commit f2c143dde123a99832bfc6eb379b82ba4a3e0103 (HEAD)
git log
# 查看分支,,依然在 detached HEAD 7698f1b6 分支工作(有 * 表示就是当前工作分支)
git branch
# 此时我们切换到其他分支,这里切换到 main 分支,会有警告:您正丢下 1 个提交,未和任何分支关联。按照提示解决就好,之后把新建的分支合并回去即可
git switch main
# 此时查看分支已经不存在之前的 detache HEAD 7698f1b6 分支了
git branch
# 解决:这里切换分支的时候提示在 f2c143d 的提交上创建新的分支
git branch detached-head f2c143d
# 此时查看分支,多了上一个命令操作创建的新分支 detached-head
git branch
# 此时切换到 detached-head 该分支就可以进行相应的修改添加删除操作了
git switch detached-head
# 如果需要把 detached-head 分支合并到其他分支,就需要先切换到其他分支,在执行合并操作命令,这里把 detached-head 分支合并到 main 分支
git switch main
# 把 detached-head 分支合并到 main 分支
git merge detached-head
# 如果还想回到某一次 commit 的地方,这里回到 83787bbd 的地方去对任何文件做操作
git checkout 83787bbd
# 修改文件
echo "This was also added in detache headmode!" >> 1.txt
# 查看分支,又产生了指向 83787bb 提交的 分离头指针
git branch
# 如果在分离头指针的分支上做了任何修改需要合并到其他分支,那就 add commit 后切换到对应的分支,把指向某次commit的分离头指针的新建的分支合并过去即可
git branch detached-head-solution # 在当前的分离头指向的分支创建新的分支
# 查看分支,多了 detached-head-solution 分支,分离头指向的分支还在
git branch
# 切换分支,这里切换到 main,因为要合并 detached-head-solution 分支修改的内容到 main 分支,此时通过 git branch 查看分支,之前指向分离头的分支已经不存在了
git switch main
# 把 detached-head-solution 分支修改的内容合并到当前工作的分支,这里当前工作的分支是前面刚切换过类的 mian 分支
git merge detached-head-solution
# 删除不需要的分支即可,删除多个分支,使用空格隔开
git branch -d detached-head detached-head-solution
git 恢复到工作区、暂存区、还原修改的文件流程
git init
初始仓库,就会自动检测文件。git add
把新的未跟踪的文件和已经修改过的文件添加到咱存区。git commit
把已经存储到暂存区的所有文件添加到版本库。git reset -soft xxx
把版本库的文件恢复到暂存区。git reset HEAD
把已经存储在暂存区的文件恢复到索引(Index)区,索引(Index)区:就是在工作区的自动检测未跟踪和已改的文件区域。git checkout -- xxx
把已经添加到暂存区的文件恢复到工作区,就是未做任何修改的原始文件。git reset --mix xxx
把版本库的文件恢复到索引区。git rest --hard xxx
把版本库的文件恢复到工作区。
隐藏暂时修改的文件 git stash
# 如果正在修改文件,突然有紧急情况修复 bug,那么又不想 commit 当前所做的修改,那么就需要暂时隐藏修改的所有文件 ,去紧急修复 bu ,修复完 bug ,再回来从暂时隐藏的修改记录中恢复出来继续工作。
# 前提已经有修改的文件了,现在暂时隐藏一下修改的文件,之后就可以去修复 bug 了
git stash
# 可以通过 git reflog 查看到这一个命令操作
git reflog
# 修复完 bug 之后,回来恢复之前通过 git stash 命令暂时隐藏的文件修改,继续工作
git stash apply
# 查看所有的暂时隐藏的修改记录
git stash list
# 如果需要指定恢复到某一次暂时修改的文件,执行 git stash apply 1 # 1 是 stash@{1} 是大括号中的数字
git stash apply 1
# 如果此时警告不能操作,再临时保存一下,git stash
git stash
# 再一次从之前临时隐藏的修改恢复出来继续工作,执行 git stash apply 2 # 2 是 stash@{2} 是大括号中的数字
git stash apply 2
# 注意:上面直接是通过 git stash 直接隐藏的,没有一些提示信息,不友好,那么如何在暂时隐藏的时候添加一些注释信息,git stash push -m "xxx"
git stash push -m "xxx feature added!"
# 使用 pop 恢复 push 暂时隐藏的修改的文件
git stash pop 0 # 0 是 stash@{0} 是大括号中的数字
# 删除暂时隐藏的操作的某一条记录日志
git stash drop 0 # 0 是 stash@{0} 是大括号中的数字
# 删除暂时隐藏的操作的所有记录日志
git stash clear
# 使用 git stash list 查看是否有隐藏的修改的记录日志
git stash list
git reflog
查看那所有的操作日志记录
git reset --hard hash值
恢复某一次的提交
# --hard,会把工作区也恢复到最初状态,如果回滚到某一次的提交,那没某一次提交后的所有修改都没了,多个人员合作那就尴尬了
git reset --hard HEAD~1
# 列出所有的操作
git reflog
# 恢复丢失的数据
# 回滚到某一次的 commit
git reset --hard 76f5fb5 # 76f5fb5 就是需要回滚的 commit hash 值
# 之前的提交也回来了
git log
git checkout hash值
恢复某一次的提交
# 创建一个 feature 分支
git checkout -b feature # git switch -c feature
# 在该 feature 分支上操作,修改文件,添加,删除后 commit 到本地版本库后,在其他分支工作的时候,不小心把 feature 分支给删除了,如果想恢复怎么解决?如下操作即可
# 列出所有的操作
git reflog
# 恢复丢失的数据
# 回滚到某一次的 commit,此时会有提示,按照提示操作,创建分支即可
git checkout 731a944 # feature # commit 的 hash 值,也可以是分支名:有检出某个分支的作用
# 此时查看分支,多了一个头指针指向某一次提交的分支,且是当前工作分支(有 * 标识为当前工作分支)
git branch
# 在头指针指向的分支创建新的分支
git switch -c feature # feature 是任意名
# 之前的提交也回来了
git log
合并
git merge
快进合并
mkdir test
cd test
git init
mkdir main
touch main/m1.txt
git add main/m1.txt
git commit -m "m1.txt file added"
touch main/m2.txt
git add main/m2.txt
git commit -m "m2.txt file added"
# 创建并切换到分支工作
git switch -c feature
mkdir feature
touch feature/f1.txt
git add feature/f1.txt
git commit -m "f1.txt file added"
touch feature/f2.txt
git add feature/f2.txt
git commit -m "f2.txt file added"
- 把 feature 分支合并到 main 分支:
git merge
# step 1:切换到 main 分支
git switch main
# step 2:开始合并 feature 分支到 main 分支
git merge feature
# 查看日志记录中已经有 feature 的 commit 的记录了
git log
# 这里 log 记录是两次提交操作,所以回滚到最初创建分支时候的状态是 HEAD~2
git reset --hard HEAD~2
注意:git merge xxx
直接合并的时候会随便执行 commit 的命令提交到本地版本库中了
会把所有的 feature 分支中 commit 的日志记录也合并到 main 分支了。
git log
查看没有本次执行合并命令的提交记录,但是有所有 feature 分支中的所有提交日志记录,不会产生新的合并提交,只是移动了头指针指向
- 把 feature 分支合并到 main 分支:
git merge --squash
# step 1:切换到 main 分支
git switch main
# step 2:开始合并 feature 分支到 main 分支
git merge --squash feature
# 查看日志记录中没有存在 feature 的 commit 的记录,只是执行了 git add 操作,添加到暂存区了,通过 git status 可以查看
git log
git status
# 再次执行 git commit -m 操作,提交到本地版本库中
git commit -m "merge feature branch into main branch"
# 查看日志记录中已经有了本次 commit 的日志记录
git log
注意:git merge --squash xxx
合并的时候会执行 git add
的命令提交到暂存区中,通过 git status
可以验证,不会有 git commit
的提交操作。
不会把 feature 分支中所有提交的日志记录也合并到 main 分支了。git log
查看日志记录只有本次执行合并命令的提交的日志记录,不会产生头指针的移动,只是先add到暂存区,还需要用户再次 commit 才会提交
非快进合并
- 把 feature 分支合并到 main 分支:
git merge --no-ff
# step 1:切换到 main 分支
git switch main
# step 2:开始合并 feature 分支到 main 分支
git merge --no-ff feature
# 查看日志记录中存在 feature 的 commit 的所有记录,还有一次是 `git merge --no-ff feature` 该操作的一次提交日志记录
git log
# 这里 log 记录是貌似是三次提交操作,所以回滚到最初创建分支时候的状态是 HEAD~3,但是实际不是的只是一次提交,所以是 HEAD~1
git reset --hard HEAD~1
注意:git merge --no-ff xxx
直接合并的时候会随便执行 commit 的命令,git log
可以查看
不仅把 feature 分支中所有提交的日志记录也合并到 main 分支了并且还把执行 git merge --no-ff xxx
命令的提交也存在日志记录中 。
git log
查看日志记录处理 feature 分支的所有提交记录,还有本次合并命令操作的提交日志记录,产生头指针的移动
如果合并到的当前分支有文件添加,这里 main 分支有改动
# 在 main 分支下工作,添加一个 m3.txt
tocuh main/m3.txt
git add main/m3.txt
git commit -m "m3.txt file added"
# 把其它分支合并到 main 分支,这里是其他分支是 feature 分支
git merge feature # 已经 commit 到本地版本库中了
# 或
git merge --squash feature # 只是 add 到暂存区
git commit -m "Merge branch feature into main" # 需要再次手动提交,才到本地版本库中
git rebase
# 有两个分支 main 和 feature
# step 1:如果想把 feature 分支合并到 main 分支上,首先切换到 feature 分支
git switch feature
# step 2:执行命令 git rebase 进行变基
git rebase main
# step 3:切换会要合并到的 main 分支进行合并,把 feature 分支合并到 main 分支中
git merge feature
# 查看日志记录,没有多余的任何提交
git log
git cherry-pick
# 有两个分支 main 和 feature
# 确定在 main 分支下工作
git branch
echo "Some import feature!" >> main/m1.txt
git add main/m1.txt
git commit -m "added text to m1.txt"
# 创建并切换到分支 feature-2
git checkout -b feature-2
# 在 新建的 feature-2 分支下工作
mkdir new-feature
touch new-feature/f-new-1.txt
git add ./new-feature/f-new-1.txt
git commit -m "f-new-1.txt file added"
# 此时发现 main/m1.txt 中有错误的单词,修改后
echo "Some important feature!" > main/m1.txt
git add main/m1.txt
git commit -m "m1.txt text fixed"
# 继续工作
touch new-feature/f-new-2.txt
git add new-feature/f-new-2.txt
git commit -m "f-new-2.txt file added"
# git log 拿到 修改错误单词的那次提交的 hash 值 02411a5cc4
git log
# 切换到 main 分支
git switch main
# 只是合并在 feature-2 分支中开发是发现出错时的修改的提交 02411a5cc4
git cherry-pick 02411a5cc4
# 查看文件 main/m1.txt,已经修改了
cat main/m1.txt
# 查看日志记录,也把其在 feature-2 分支中修改提交的记录合并到 main 分支中了
git log
Merge VS Rebase VS Cherry-Pick
处理合并冲突(Handling merge conflicts)
git branch # 查看当前工作的分支
# 在 main 分支,修改 feature/f1.txt 文件
echo "This is the change made in the main branch!" >> f1.txt
git add feature/f1.txt
git commit -m "change in main branch for f1.txt file"
# 切换到 feature 分支
git switch feature
# 在 feature 分支也修该了 feature/f1.txt 文件
echo "I changed this in the feature branch!" >> f1.txt
git add feature/f1.txt
git commit -m "change in feature branch for f1.txt file"
# 切换会 main 分支
git switch main
# 开始把 feature 分支合并到 main 分支中
git merge feature
# 此时会产生冲突
# 如果解决冲突后还是有问题项目运行或者解决过程中混乱了,没有任何的下一步的 git 命令操作,就使用 git merge --abort 抛弃合并过程并且尝试恢复到合并前的状态。
# 该命令仅仅在合并后导致冲突时才使用
git merge --abort
# 再次合并,冲突依然存在,依然继续解决冲突
git merge feature
# git diff 查看冲突的文件差异
git diff
# 解决完冲突,查看状态
git status
# add 后 commit
git add filename # git add . # . 表示所有的
git commit -m "Merge branch feature into main and fix conflict"
标签 (Tag)
git log
# 指定某一次的提交,打一个标签(tag)
git tag 1.0.0 316cec89194
# 查看 tag
git tag
# 删除某个tag
git tag -d 1.0.0
# 显示某个标签的信息
git show 1.0.0
# 可以使用 checkout 签出某次的 tag
git checkout 1.0.0
# 此时通过 git branch 查看分支会产生头指针的指向该 tag 的分支,如果需要回到其他分支,直接切换分支即可
git branch
git checkout main
# 创建带有注释信息的 tag
git tag -a v1.0.1 -m "version 1.0.1 released" 375eac7bd
# 查看相应的 tag 信息
git show v1.0.1
远程分支
分支远程(上游)追踪
# 查看远程仓库所有分支
git ls-remote
# 把本地仓库和远程仓库关联 origin 可所以任意名做仓库标识
git remote add origin https://gitee.com/www-ly-cn/demo.git
# 查看远程的仓库标识
git remote
# 如果存在远程标识,可以删除远程配置
git remote rm origin # origin 就是远程标识
# 指定推送到 main 分支
git push -u origin main
# 查看所有的分支(本地和远程的)
git branch -a
# 只查看远程的所有分支
git branch -r
# 在远程仓库中新建分支,如果本地通过 git branch [-a/-r] 是不全的,再次 git fetch origin 一下
# 获取 origin 标识的相关分支(origin是 推送到远程仓库时设置的标识)
git fetch origin # git fetch 只是 copy
# 或者指定对应的远程的标识的分支进行拉取
# 指定对应的远程仓库的分支拉取(git pull = git fetch + git merge)
git pull origin feature
# 查看仓库分支的上游跟踪情况
git branch -vv
git remote show origin
# 本地不存在 xxx 分支,就建立好分支 xxx 并已追踪 origin/old(origin/old是远程已经存在)
git branch --track xxx origin/old
# 本地已经存在的分支 xxx,想要设置 upstream 分支,调用 --set-upstream-to
git checkout xxx && git branch --set-upstream-to=origin/old # (origin/old是远程已经存在)
# 或者一步到位
git branch --set-upstream-to=origin/old xxx
# 本地创建分支并推送到远程时,远程就会多了一个新的分支
git switch -c new-xxx # 或 git checkout -b new-xxx
# 可以对该新分支中的文件做修改之后在推送的,这里就直接推送了
git push origin new-xxx
# 如果有 -u 选项,表明已经添加了上游追踪,下次推送该分支,可以直接使用 git push 推送
# git push -u origin new-xxx
删除/或推送远程分支
# 查看远程分支
git ls-remote
git branch -r
# 查看分支
git branch -a
# 请求远程某个标识的所有分支到本地,这里是 origin 的标识
git fetch origin
git branch -a
- 删除远程分支
# 删除本地分支
git branch -D feature
# 删除远程跟踪分支
git branch --delete --remotes origin/feature
# git branch -a 查看没有了
git branch -a
# git ls-remote 查看还存在,说明远程对应的分支还没有删除掉
git ls-remote # 或者去网页查看还存在
# 需要推送一下,才可以删除远程的分支
git push origin --delete feature
# git ls-remote 查看已经没有了,说明远程对应的分支已经删除掉
git ls-remote # 或者去网页查看也不存在了
# 不删除本地分支,去直接删除远程分支
git push origin --delete xxx