比如有 commit asda21313123,我给它打了 tag v100 ,如果使用git revert git revert v100..HEAD
的方式,如果中间有 merge commit 就不行。
要求不能用 reset 、 rebase 这样重写提交记录的方法。
1
jsfaint 2016-08-01 11:00:20 +08:00
为啥不能用 git reset ?
git reset --hard 不就是做这事的吗? |
2
henius 2016-08-01 11:08:59 +08:00
git reset --hard
|
3
hosiet 2016-08-01 11:13:22 +08:00 via Android
为啥不能用 git reset?
说实在的,只想检出代码又怕影响历史纪录的话, git checkout 都行,就是不知道你的需求是什么 如果想用一个提交解决一切, git diff 导出区别再 apply 如何? |
4
zeroten OP |
6
Havee 2016-08-01 11:50:54 +08:00
你的需求到底是什么,有点看不懂。
如果要从 v100 从头开始来过, reset/checkout 都行,最好是 checkout 个分支,人家仍然 push 到原分支。 |
7
zeroten OP 简而言之, reset 可能会给团队中其他人带来困扰,且 reset 太暴力,操作不当可能丢失提交记录
|
9
zeroch 2016-08-01 12:05:47 +08:00
你要知道, 如果你在 remote master branch 上进行了回滚操作,然后在 push 回到 master 上面.那么, 无论如何你已经和 diverge, *不可避免*的对别人造成影响..
如果你在 local 的任意 branch 上操作..上面的回复说的, 不论是 reset 还是 checkout 都是可以的。甚至还有一种方法.你先 checkout 1, 然后从 1 到 4 进行 cherry-pick 。 cherry-pick 不会 hash 出新的 commit id 。 |
10
fangdingjun 2016-08-01 12:26:34 +08:00
像这样, 用历史文件覆盖当前文件,并产生一个新的 commit
git checkout -b temp git reset --hard c7 git archive HEAD > /tmp/t.tar git checkout master tar xf /tmp/t.tar git add . git commit -m 'reset to c7' |
11
axb 2016-08-01 12:32:04 +08:00
推荐看下这篇, Linus Torvalds 写的:
http://opensource.apple.com/source/Git/Git-26/src/git-htmldocs/howto/revert-a-faulty-merge.txt |
12
xi_lin 2016-08-01 12:42:51 +08:00
|
13
BOYPT 2016-08-01 13:26:37 +08:00
感觉就像朋友圈里面那些不许用方程解小学数学题,好难~
|
14
networm 2016-08-01 15:48:45 +08:00 via iPhone 1
git reset --hard 4
git reset --soft 8 git commit -m 'Reverted 5 6 7 8' 其实楼主怕的是丢失提交记录,而不是使用 reset rebase 命令 |
15
julyclyde 2016-08-01 15:52:01 +08:00
revert 是回滚某个 commit ,不是回滚“到”某个
你需要 checkout 或者 reset 之类的 |
16
zzzreg 2016-08-01 16:51:34 +08:00
切个新 branch 再 reset 怎么样?
|
17
pagxir 2016-08-01 17:03:48 +08:00 via Android
这么简单的操作,有你们想的那么复杂吗。
git rm -r -f * git checkout <rev> . git commit -m xxxx 就所有文件恢复到版本 rev 的状态,同时不进行分支修剪。 |
18
zeroten OP @julyclyde 你看我主题中发的 git revert git revert v100..HEAD ,就有了回滚“到”的效果,只是有 merge commit 就不行了
|
20
zeroten OP |
21
lightening 2016-08-01 17:51:42 +08:00
赞同 @networm
你 reset 后并不 force push ,不会修改 history 的。 他所做的本质上就是手动提交一个新 commit ,其内容是 revert 你的那些 commits 。 我稍微修改一下,帮助理解,本质上和 @newworm 是一样的: git checkout 4 # 把你 checkout 的代码状态更新到 4 的状态,此时你是 detached HEAD 状态,没有在任何 branch 上 git reset --soft <your_branch_name> # 把你的 branch 状态回复到原先的 branch 。因为是 soft reset , checkout 的代码还是 4 的状态 git add . git commit -m "Revert 5 6 7 8" # 此时再提交一个新的 commit 。由于你的代码是 4 的状态,但是你此时 history 处于 8 的位置,再移交一个 commit 就是 9 了。其内容正好是变回 4 的状态,也就是说实际上 commit 9 正好 revert 了 5 6 7 8. |
22
clino 2016-08-01 17:58:16 +08:00
"且 reset 太暴力,操作不当可能丢失提交记录" 怕丢历史就先新建一个 backup 分支
|
23
zxq1002 2016-08-01 18:06:47 +08:00 via Android
git branch tmp
git checkout tmp git reset --soft 4 git commit -m "revert from 8 to 4" git checkout <your branch> git cherry-pick <the hash id of commit: revert from 8 to 4> or git merge tmp git branch -d tmp |
24
zxq1002 2016-08-01 18:11:38 +08:00 via Android
@zxq1002 不好意思,少了 git reset --soft <the hash id of commit: revert from 8 to 4>
git commit -m "revert" 同意 21 楼答案 |
25
jsfaint 2016-08-01 18:11:44 +08:00
@zeroten reset,rebase 用在本地的 unmerged branch 上有什么关系?
在远端即使你使用 revert 也依然会对其他人造成困扰的。除非对应的 branch 只有你一个人在用,不过既然只有你一个人用, rebase , reset 又有什么关系呢…… |
26
lightening 2016-08-01 18:11:59 +08:00 1
OK 找到一个更清晰的方法:
git checkout 4 -- ./ # 直接取出 4 的代码,不改变 branch git commit -m "Revert 5 6 7 8" # 然后提交 commit 9 |
27
xqin 2016-08-01 18:20:07 +08:00
@zxq1002 按你的做法, 最终 cherry-pick 的时候, 会得到一个提示:
nothing to commit, working directory clean 因为你在 commit 那步 提交的文件与你 原分支上的代码是一样的, 所以最终 cherry-pick 会显示没有什么可拿过来的, 如果非要拿过来, 请加一个 --allow-empty 参数. |
28
xqin 2016-08-01 18:40:14 +08:00
@lightening 你的方法存在问题吧?
楼主已经说了 他要 revert 的内容中有 merge , 你直接从某个 commit 点提取出来的代码, 并不是 revert 后的结果. 举个最简单的例子. ==10 ==9 8===6 7===5 ==4 ==3 ==2 ==1 > 由于 v2 在评论中对格式展示的不好, 所以用 = 号来表示空格, 请自行替换后, 感受一下 git log 目前的情况. 9 是由 6/8 合并而来, 现在要还原的 commit 为 10,9,6,5 按你的做法是 checkout 4 -- ./ 然后 commit 这么做的后果是 8/7 的 commit 没了. 楼主的情况应该就是这种, 所以 git 要求他, 选择 parent. |
29
zeroten OP @xqin 那有没有什么好的方法能不收购处理 merge commit 呢?比如“ 2016 年 7 月 1 日 3 点上线的那个版本”,这个版本是明确的,我应该如何能记录这个版本,并且能够方便快速的回滚的,目标是一行命令或者脚本,且不需要人工干预。
|
31
xi_lin 2016-08-01 19:03:23 +08:00
@zeroten 不过正常来说 master 上的都是 fast forward 的 merge ,用楼上给的 reset soft 也不是不行
|
33
xqin 2016-08-01 19:05:46 +08:00
@zeroten 你不都已经打了 Tag 了吗? 那还 revert 什么?
你直接从那个 tag 中检出一个分支, 然后你想干嘛干嘛嘛. 另外代码回滚 是你发布工具的事情 与 git 无关, 如果你代码中有 bug,只管在 git 中修复即可. 线上的代码如果要回滚的话, 一般情况下 发布系统(至少我们发布系统会)都会有保留之前站点前几个版本的内容, 比如每次使用的时候使用不同的文件夹, 如果要回滚, 直接将站点切回之前的文件夹即可. 根本不需要 git 参与嘛. 比如当前的代码在 A 目录, 然后发布一次使用 B 目录, 再发一次使用 C 目录, 如果 C 目前的代码有问题,直接将站点切换回 B 目录即可. |
34
lightening 2016-08-01 19:23:32 +08:00
@xqin 因为楼主一直说是要“回滚到”某个以前的版本,我觉得他其实就是想把所有的 merge 都不要了。
楼主说“ 2016 年 7 月 1 日 3 点上线的那个版本”这个需求,应该就是所有的 commit 都不要的意思吧。 |
35
caiya21 2016-08-01 20:26:21 +08:00
楼主可以考虑 用下 source tree (逃
|
36
HackerOO7 2016-08-01 21:09:57 +08:00
git branch newbranch commitid
|
37
zhx1991 2016-08-01 21:47:35 +08:00
太长了
我就一个问题 中间的提交还要不要 |
38
msg7086 2016-08-02 03:39:48 +08:00 3
重写分支太危险 -> 你需要一个好用的工具。我做历史重写从来没丢过东西。
至于 reset ,谁告诉你 reset 一定要重写历史的? 如果你要让线上的版本滚回到精确的某个提交的状态,那么先 checkout 历史提交,然后做 reset mixed 到 HEAD ,再做一次提交就行了,这个提交就包含了两者之间所有更改的 revert 。 git checkout 4 # 回到历史 git reset --mixed master # 把历史带到脑袋 git checkout master # 签出脑袋 git commit # 把历史和脑袋的 revert diff 提交 |
39
cszhiyue 2016-08-02 09:13:30 +08:00
|
40
xx314327475 2017-03-22 11:33:41 +08:00
@msg7086 就服你,比人不服
|
43
njwangchuan 2018-07-09 14:35:55 +08:00
用了 @newtorm 的方法感觉挺好,请问有啥副作用没。
|
44
williamwue 2018-08-03 10:24:01 +08:00
@msg7086 非常棒的方案!实测通过
|
45
njwangchuan 2021-01-15 11:27:22 +08:00
@msg7086 简单,实用,解决了大问题。
|