likes
comments
collection
share

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

作者站长头像
站长
· 阅读数 14

git reflog 解决提交代码丢失 detached-head

reflog 是 Git 操作的一道安全保障,它能够记录几乎所有本地仓库的改变。包括所有分支 commit 提交,已经删除(其实并未被实际删除)commit 都会被记录。总结而言,只要 HEAD 发生变化,就可以通过 reflog 查看到。

detached-head 代码丢失找回

背景

日常开发中,切换分支误操作,造成本地代码修改丢失。

此时,可以借助 git reflog 找回丢失的代码修改。

丢失产生原因和步骤

首先在 master 分支上开发,此时线上出现 bug 且回到旧版本的 tag。这时 master 分支上有一部分代码修改但未提交。

master 分支上执行 git status,有未提交的代码,如下图所示

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

master 分支上执行 git tag查看标签信息,如下图所示

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

此时有未提交的代码,然后执行 git checkout v1.0

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

这个时候,提示当前分支为 detached HEAD

然后再执行 git add ./git commitgit checkout master,切换回 master 分支。这个时候发现 detached HEAD 分支不见了,master 分支上未提交的代码也不见了。

代码找回

执行 git reflog 查看提交记录

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

查找对应提交的 commitId247e11b,然后执行下述命令行,找回丢失的代码

git checkout 247e11b    //检出对应的提交
git checkout -b diff    //新建一个新的diff分支
git checkout master     //切换到master分支
git merge diff          //将新建的diff分支合并到master分支

删除所有历史提交记录

此处介绍如何删除所有历史提交记录,形成一个全新的仓库。

  • 1 - Checkout
git checkout --orphan new_branch
  • 2 - Add all the files
git add -A

//等效于 git add --all 或 git add .

git add 中使用参数 -A--all 表示追踪所有操作,包含新增、修改和删除

Git 2.0版开始,-A 参数为默认参数,即 git add . 等效于 git add -Agit add --all

  • 3 - Commit the changes
git commit -am "commit message"
  • 4 - Delete the branch
git branch -D master   //同时删除本地和远程分支
  • 5 - Rename the current branch to master
git branch -m master
  • 6 - force update your repository
git push -f origin master

下面对上述步骤进行说明

git checkout --orphan

如果你的某个分支上积累了无数次的无意义的提交,git log 信息满天飞,那么可以使用 git checkout --orphan <new_branch_name>

  • 基于当前分支创建一个新的“孤儿(orphan)”的分支,没有任何提交历史,但包含当前分支所有内容
  • 执行上述命令后,工作区(Workspace)中所有文件均被认为在该操作中新增(git statue 查看状态,所有文件状态均为 new file,如下图所示),此时执行 git add . 会把所有文件添加到缓存区(Index

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

  • 严格意义上说,执行 git checkout --orphan <new_branch_name> 后,创建的并不是一个分支,因为此时 HEAD 指向的引用中没有 commit 值。只有在进行一次提交后,它才算得上真正的分支。

orphan 译为“孤儿”,该参数表示创建一个孤立的分支,没有任何提交历史,且与当前分支不存在任何关系(查看提交信息,可发现其为一个孤立的点,如下图所示)

孤儿(orphan)无父辈信息,同理,创建的分支也不包含任何历史提交信息

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

git commit -am

git branch -m

重命名

git push -f origin master

git 项目协作——保证git信息简洁

同一分支 git pull 使用 rebase

默认情况下,git pull 使用的是 merge 行为。多人协作开发时,会产生不必要的 merge 提交记录,造成提交链混乱不堪。

推荐在同一个分支更新代码时,使用 git pull --rebase

# 为某个分支单独设置,这里是设置 dev 分支
git config branch.dev.rebase true
# 全局设置,所有的分支 git pull 均使用 --rebase
git config --global pull.rebase true
git config --global branch.autoSetupRebase always

分支合并使用 merge --no-ff

Usage

  • Fast-Forward:当前分支合并到另一分支时,如果没有冲突要解决,就会直接移动文件指针,并且不会产生合并提交记录。该过程中,存在git 文件指针快速移动, 因此该过程称为 Fast-Forward
  • --no-ff(no fast foward):每一次的合并,都会创建一个新的 commit 记录。使用 --no-ff,可以保持原有分支提交链的完整性,并且当该分支被删除时,提交信息依旧存在。

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

结合上图分析,在 dev(绿色) 分支上检出 feature-1 分支(蓝色),且 dev 分支不进行任何提交

  • 直接 merge,默认采用 Fast-Forward,两个分支的提交链会合并为一条直线,不利于后期代码审查和维护
  • 使用 git merge --no-ff feature-1 合并代码,会产生一个新的提交,且两个分支的提交链不会重叠,利于后期代码审查和维护

merge 默认设置

git merge 默认使用 fast-forward,可以通过如下方式,修改为默认使用 --no-ff

git config --global merge.commit no
git config --global merge.ff no

此外,SourceTree 在设置中也可以设置 --no-ff

Git进阶使用——git reflog处理代码丢失 & 协作开发保证git信息简洁

转载自:https://juejin.cn/post/6844904055232282632
评论
请登录