【问题标题】:Git, "move" a commit exactly as it is without merge filesGit,在没有合并文件的情况下完全“移动”提交
【发布时间】:2016-11-29 18:22:36
【问题描述】:

在 git 中我遇到了这样的情况:

a - b - c - d - #be2c15
                    ^

我想从提交“a”中恢复一些文件,所以我做了一个重置​​ SOFT 而不修改工作树

a - b - c - d - #be2c15
^

然后我恢复了标记为已删除的文件。

此时我不得不将索引重置为 #be2c15 然后执行提交,但我犯了一个错误并立即提交了更改,如下所示:

a - b - c - d - #be2c15
 \
  #88ae59e

现在提交 #88ae59e 包含我想要的所有内容,但位置错误。如何在不触及其中包含的任何文件的情况下“移动”它? 像这样:

a - b - c - d - #be2c15 - #88ae59e

【问题讨论】:

  • 这不是变基吗?或者也许是樱桃采摘?
  • @melpomene rebase 将在#be2c15 之上应用从a#88ae59e 的差异。这与使用父级 #be2c15#88ae59e 的树创建新提交完全不同,我相信这是 OP 正在尝试做的事情。

标签: git git-commit git-reset


【解决方案1】:

我认为 git rebase 可以工作(但取决于在执行 rebase 时可能会发生合并冲突之间的变化)。

之后

$ git rebase be2c15 88ae59e

可能还有一些合并冲突修复,你可能会得到你想要的。

使用git rebase --abort 还原


但是如果您想恢复一些已删除的文件,可能会有更简单的方法来做到这一点。

来自关于git checkout的git文档

git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>…​

&lt;paths&gt;--patch 给出时, git checkout 切换分支。它从索引文件或命名的&lt;tree-ish&gt;(通常是提交)更新工作树中的命名路径。

所以

$ git checkout a -- path-to-folder/or/file/

将检查path-to-folder/or/file,因为它是在提交时a

【讨论】:

  • 但是结帐也应该将索引移动到设计的提交,对吗?实际上我猜是否有办法获取 #be2c15 中剩余的提交 #88ae59e 的确切内容。

    否则我必须:
    1. 结帐 #88ae59e
    2. 复制工作临时未版本化文件夹中的树
    3. 结帐 #be2c15
    4. 用临时文件夹替换他的工作树
    5. 提交它

    git 不这样做对我来说似乎很奇怪提供自动执行此操作的命令
  • 我希望我的编辑能够更好地/更多地阐明git checkout -- some-file 的用法。
  • 不幸的是它不起作用,在任何情况下执行 checkout 命令时 git 都会在工作树中进行一些操作(询问他必须如何处理冲突)
  • 您在要使用git checkout -- path/to-file 恢复的文件中是否有未提交的更改?您需要先暂存或提交它们。
【解决方案2】:

假设您想使用 #88ae59e 的树创建提交,这个命令序列应该可以解决问题:

git checkout 88ae59e    #checkout the tree that you want to commit
#you should be in detached head state now
git reset --soft master #switch HEAD to the intended parent commit
#you should still be in detached head state now
git checkout master     #reattach to your branch so it will see the following commit
git commit ...

如果你在分离头状态下执行git reset --soft,你不会离开分离头状态,所以你需要在重置后通过第二个git checkout将你的HEAD指向分支。

【讨论】:

  • 在结帐命令之前,一切都按我的意愿工作。它不仅重新附加分支,还尝试将文件合并到工作树中
  • 我认为,您应该通过比较git show -s HEADgit show -s master 的输出来验证您的HEAD 指向与您的master 相同的提交。这两个必须相同;如果是,git checkout master 将是即时的并且不会失败,因为它不需要接触任何文件。 (第二个checkout 的唯一和预期效果是从HEAD -&gt; be2c15 状态移动到HEAD -&gt; master -&gt; be2c15 状态,因此下面的commit 将前进master 而不仅仅是HEAD。)
【解决方案3】:

你可以在 git 之外很容易地做到这一点,以避免任何可能的冲突或刺激:

git checkout 88ae59e
tar cf /tmp/tmp.tar --exclude=.git 
git checkout be2c15
tar xf /tmp/tmp.tar ; rm /tmp/tmp.tar
git add... ; git commit

【讨论】:

    猜你喜欢
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-08-11
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多