likes
comments
collection
share

Git工作使用笔记

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

分离头指针

当前分支图

Git工作使用笔记

切换到之前的某一次提交

Git工作使用笔记

执行命令

$ git checkout de11fa87ea

提示,当前位于“分离头指针”状态

Git工作使用笔记

分支图

Git工作使用笔记

注意

  • 在分离头指针状态下没有绑定分支
  • 产生的commit不会被保存
  • 分支切换后在分支图中看不到该commit
  • 一段时间后会被git自动清除

使用场景

  • 尝试性做一些变更,可以随时丢弃

此处演示分离头指针丢失commit的情况和补救措施

丢失commit

使用IDE修改文件并提交,忽略所有警告,修改后分支图如下

Git工作使用笔记

此时接到其他需求,需要切换分支进行紧急修复

执行命令

$ git checkout master

分支切换成功,并弹出提示和告警

Warning: you are leaving 1 commit behind, not connected to any of your branches:

199ac20 游离状态修改文件

If you want to keep it by creating a new branch, this may be a good time to do so with:

git branch 199ac20

Switched to branch 'master' Your branch is up to date with 'origin/master'.

Git工作使用笔记

此时查看分支图,刚才的commit已经不可见

Git工作使用笔记

补救

此时发现刚才的commit十分重要,可根据git的提示进行补救

执行命令

$ git branch hot-fix 199ac20

再次查看分支图,可见commit已经恢复

Git工作使用笔记

本地分支操作

以下操作仅适用于本地分支,无远程分支协同工作的情况

修改当前commit的message——amend

当前分支图

Git工作使用笔记

执行命令

$ git commit --amend

自动弹出编辑器

Git工作使用笔记

修改后保存并关闭编辑器即可,输出如下

Git工作使用笔记

再次查看分支图

Git工作使用笔记

修改前面某次commit的message——rebase

现计划修改如下message

Git工作使用笔记

使用IDE拷贝其父提交的SHA值

Git工作使用笔记

执行命令,-i表示交互式执行

$ git rebase -i 199ac203c90f881024c6870d56517df9e2080841

自动弹出编辑器

Git工作使用笔记

同时包含提示操作

Rebase 199ac20..bfe2b7f onto 199ac20 (3 commands)

Commands: p, pick = use commit r, reword = use commit, but edit the commit message e, edit = use commit, but stop for amending s, squash = use commit, but meld into previous commit f, fixup = like "squash", but discard this commit's log message x, exec = run command (the rest of the line) using shell b, break = stop here (continue rebase later with 'git rebase --continue') d, drop = remove commit l, label = label current HEAD with a name t, reset = reset HEAD to a label m, merge [-C | -c ] [# ] . create a merge commit using the original merge commit's . message (or the oneline, if no original merge commit was . specified). Use -c to reword the commit message.

These lines can be re-ordered; they are executed from top to bottom.

If you remove a line here THAT COMMIT WILL BE LOST.

However, if you remove everything, the rebase will be aborted.

Note that empty commits are commented out

由此可见“变基”支持很多操作,此处需要使用的是reword,修改目标提交的命令为r

Git工作使用笔记

保存并关闭编辑器,会自动弹出新编辑器界面

Git工作使用笔记

修改后保存并关闭即可,输出如下

Git工作使用笔记

查看分支图

Git工作使用笔记

整理连续多个commit——rebase

现计划合并3个commit

Git工作使用笔记

使用IDE拷贝其父SHA值

Git工作使用笔记

执行命令

$ git rebase -i 199ac203c90f881024c6870d56517df9e2080841

此处使用squash,官方介绍如下

s, squash = use commit, but meld into previous commit

修改内容如下,说明将中间两个合并进第一个commit中

Git工作使用笔记

保存后关闭,会弹出新的编辑器界面,提示可以输出合并commit的message

Git工作使用笔记

编写message

Git工作使用笔记

保存后关闭,提示修改成功

Git工作使用笔记

查看分支图

Git工作使用笔记

分支合并策略

演示不同分支合并策略效果,当前的分支图如下

Git工作使用笔记

现在将hot-fix合并进master

GitLab默认合并策略——merge commit

gitlab默认合并请求使用的策略

Git工作使用笔记

Git工作使用笔记

由于没有冲突,可以线上直接合并

其对应执行的命令如下

Step 1. Fetch and check out the branch for this merge request

$ git fetch origin
$ git checkout -b hot-fix origin/hot-fix

Step 2. Review the changes locally

Step 3. Merge the branch and fix any conflicts that come up

$ git fetch origin
$ git checkout origin/master
$ git merge --no-ff hot-fix

Step 4. Push the result of the merge to GitLab

$ git push origin master

合并完成

Git工作使用笔记

查看分支图,故当前分支会影响特性分支并产生新的提交

Git工作使用笔记

GitLab合并提交策略

提交合并请求的时候勾选策略Squash commits when merge request is accepted

Git工作使用笔记

Git工作使用笔记

其对应执行的命令如下(与默认策略一致)

Step 1. Fetch and check out the branch for this merge request

$ git fetch origin
$ git checkout -b hot-fix origin/hot-fix

Step 2. Review the changes locally

Step 3. Merge the branch and fix any conflicts that come up

$ git fetch origin
$ git checkout origin/master
$ git merge --no-ff hot-fix

Step 4. Push the result of the merge to GitLab

$ git push origin master

合并成功

Git工作使用笔记

查看分支图,可见其影响特性分支,会产生新的提交,同时覆盖特性分支最后一次提交

Git工作使用笔记

分支合并策略——squash merge

GitHub支持squash merge合并策略,此处通过命令行执行测试

$ git merge --squash origin/hot-fix
$ git commit -m "squash commit"

查看分支图,特性分支不变,目标分支合并提交后产生一条提交,效果与GitLab合并提交类似,但命令使用方式不同

Git工作使用笔记

注意:squash merge会变更提交者作者信息,这是一个很大的问题,后期问题追溯不好处理

变基合并策略——rebase merge

该策略也是GitHub支持的合并策略,可能会产生较多冲突

Git工作使用笔记

选择合并策略,最后一种即变基合并策略

Git工作使用笔记

Git工作使用笔记

合并成功

Git工作使用笔记

查看分支图,其产生的三次提交即变基合并的结果,不会影响特性分支,也不会变更提交人,类似cherry pick

Git工作使用笔记

分支回滚策略

回滚策略分为两种,一种是合并后回滚,一种是普通提交回滚,不同回滚策略操作方法不同

普通提交回滚

当前分支图,计划回滚最新提交

Git工作使用笔记

直接在IDE中执行revert操作即可

Git工作使用笔记

Git工作使用笔记

回滚会产生新的提交,回滚结束

Git工作使用笔记

合并后回滚

此时分支图,使用merge commit方式进行过一次合并,此时不想要合并的结果,想恢复到未合并状态

Git工作使用笔记

错误操作——直接执行revert

此时IDE已经不支持通过revert进行回滚合并操作,通过命令行强行执行

查找SHA值

Git工作使用笔记

回滚merge需要加上-m参数git就知道到底要revert哪一个merge

$ git revert -n 25d7b405a4d50fe1b36019d90276973a8ed9160d -m 1

回滚后做一次commit即可,使用默认的message后如下

Git工作使用笔记

验证回滚结果,使用两个提交进行差异比对

Git工作使用笔记

无差异,回滚看似成功了

Git工作使用笔记

此时在原分支做了修复后再进行合并

Git工作使用笔记

报无法合并,因为分支已经进行过合并

Git工作使用笔记

正确操作——reset

使用reset操作到上一次提交

Git工作使用笔记

使用--hard参数,丢弃后续的commit

Git工作使用笔记

Git工作使用笔记

此时继续进行操作,并支持重新合并

Git工作使用笔记

禁止类操作

说明:禁止类说明是对开发人员禁止,而该命令在必要时候依然需要由配置管理员使用

push -f

官方使用说明

-f, --force force updates

原因:

  • 默认情况下远端分支若能顺利合并(fast forward),则会顺利合并
  • 若远端分支产生冲突,则会停止push,同时提示错误,要pull到本地处理冲突后重新push
  • -f之后,本地分支会强行推送到远端,若本地分支落后于远端分支也不会弹出提示,由此导致远程commit丢失

适用场景:

  • 远程分支已经混乱,本地分支符合需要,需要强制整理远程分支

公共分支禁止rebase

此处对场景进行模拟,正常情况下,多位开发者对公共分支common-branch进行修改,分支图如下

Git工作使用笔记

另一开发者在本地修改后执行变基操作,此处以修改历史提交message为例

Git工作使用笔记

变基

Git工作使用笔记

录入变基信息

Git工作使用笔记

变基成功

Git工作使用笔记

此时查看本地分支图,可见产生了新的分支路径,同时远程message并没有变化,故rebase对存在远程分支的情况无效

Git工作使用笔记

变基后推送到远端分支,提示需要合并,选择“合并”

Git工作使用笔记

合并后分支图如下

Git工作使用笔记

此时其他开发者修改文件后并fetch远程分支查看变更情况如下

Git工作使用笔记

此时无法对远程分支进行push操作

Git工作使用笔记

处理方法

pull远程分支在本地合并后重新推送,此时在本地再产生一次合并

Git工作使用笔记

此时可以成功推送

Git工作使用笔记

由此一来一回操作导致大量不必要的合并操作,并可能导致大量冲突,并且没有解决问题

警告类操作

reset --hard

官方对reset操作用法说明

usage: git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [] or: git reset [-q] [] [--] ... or: EXPERIMENTAL: git reset [-q] [--stdin [-z]] [] or: git reset --patch [] [--] [...]

-q, --quiet           be quiet, only report errors
--mixed               reset HEAD and index
--soft                reset only HEAD
--hard                reset HEAD, index and working tree
--merge               reset HEAD, index and working tree
--keep                reset HEAD but keep local changes
--recurse-submodules[=<reset>]
                      control recursive updating of submodules
-p, --patch           select hunks interactively
-N, --intent-to-add   record only the fact that removed paths will be added later
-z                    EXPERIMENTAL: paths are separated with NUL character
--stdin               EXPERIMENTAL: read paths from <stdin>

原因:

  • 在分支上执行该操作会丢失目标commit以后的所有commit

适用场景

  • 用于分支回滚且不打算保留其后的所有变更