【问题标题】:git rebase - add original commit hash to commit messagesgit rebase - 添加原始提交哈希以提交消息
【发布时间】:2019-01-14 16:15:56
【问题描述】:

有没有办法在 rebase 中做与cherry-pick -x 相同的事情(将原始提交的哈希添加到复制提交的消息中)?

我目前可以通过替换以下内容来解决它

git checkout other-branch
git rebase master
git checkout master
git merge other-branch

git checkout master
....
git cherry-pick -x other-branch^^^^
git cherry-pick -x other-branch^^^
git cherry-pick -x other-branch^^
git cherry-pick -x other-branch^
git cherry-pick -x other-branch

【问题讨论】:

  • git rebase master -x 不工作吗?
  • 不,那是在每次提交后执行一个脚本,就像在每次提交后运行测试一样。如果是这样就太好了。
  • 另外说明,你为什么要这个?
  • 因为如果您在解决冲突时犯了一个错误,有时能够查看原始版本是件好事,至少在接下来的几个小时或几天内。
  • 没有这个你也可以做到。在你变基之前做一个分支。或者查看 reflog。

标签: git rebase


【解决方案1】:

它不漂亮,但它完成了工作;

git rebase --exec='git log --pretty="format:%B" -n 1 > tmp;
    grep -o "\w\{40\}" .git/rebase-merge/done | tail -n 1 >> tmp; 
    git commit --amend -F tmp; 
    rm tmp;' master

解释--exec脚本的各个部分;

  • 将我们刚刚完成的提交信息放入tmp
  • .git/rebase-merge/done 获取我们刚刚重新设置的提交的哈希并将其附加到tmp
  • 修改我们刚刚使用tmp 作为提交消息所做的提交。
  • 删除tmp 文件。

我相信你可以把它改成你喜欢的格式。

原创作品日志;

commit 1ebdfc2fd26b0eed9f131197dc3274f6d5048e97
Author: Adam
Date:   Thu Jan 24 16:33:09 2019 +0000

    Content C

commit 632f1a4e1ab5d47c9e4c3ca3abd02a207a5dda09
Author: Adam
Date:   Thu Jan 24 16:33:06 2019 +0000

    Content B

commit a7e0d1eb2e412ec51865ccd405ea513c7677c150
Author: Adam
Date:   Thu Jan 24 16:33:04 2019 +0000

    Content A

改建工作日志;

commit 79d7ece06185b21631248a13416e5ca5c23e55b2
Author: Adam
Date:   Thu Jan 24 16:33:09 2019 +0000

    Content C
    1ebdfc2fd26b0eed9f131197dc3274f6d5048e97

commit d2fe6267165fa05f5fe489a6321b0b1742d1a74c
Author: Adam
Date:   Thu Jan 24 16:33:06 2019 +0000

    Content B
    632f1a4e1ab5d47c9e4c3ca3abd02a207a5dda09

commit da72fab2008e74f6a8e247f93619943805ebf86e
Author: Adam
Date:   Thu Jan 24 16:33:04 2019 +0000

    Content A
    a7e0d1eb2e412ec51865ccd405ea513c7677c150

【讨论】:

  • 不错!我把它变成了一个可执行文件,以便能够这样写:git rebase some-branch --exec update_commit_previous_hashes_listgist.github.com/maxlath/03cf6e6dcb525ff84f6c07b6ff58ed8e
  • 我一直在使用它,不幸的是,这可能会影响最后一次提交。当它运行两次时。 .git/rebase-merge/done 不会包含正确的信息,因为最后一次提交已经被重新定位并且没有什么可做的,但最后一次提交仍然会被修改。
  • @deadalnix 所以如果你运行两次,目标是branchA然后是branchB,最终的提交会是fubar吗?
  • 所以我进行了更多调查,但我错误地描述了这个问题,即使有一个问题。当在 rebase 期间有一个提交被跳过时,就会出现问题,例如,因为该提交的内容已经存在,然后修改确实使用已删除提交的信息修改了先前的提交。
  • 当你对相同的代码进行两次 rebase 时会发生这种情况,这最终会导致一次提交。我最终使用 filter-branch 删除所有将被删除的提交,然后重新设置基准。 idk 如果该解决方案适合您。
【解决方案2】:

所以,这是我的解决方案:

git rebase <branch> \
-ix "git rev-parse --short HEAD > tmp &&  \
echo 'from: $<branch_shortid>' > tmp && \
git commit --amend -F tmp"

确保branch_shortid 是正确的,并且是在您希望重新设置内容来自的分支上生成的。

免责声明:我不确定这是否适用于所有情况,尤其是当您有一些奇怪或复杂的引用系统正在进行时。我在一个非常简单的 git repo 上运行它:

$ git init 
$ echo "a" > a.txt && git add . && git commit -m "first commit"
$ git checkout -b "feature1" 
$ echo "b" > b.txt && git add . && git commit -m "second commit"
$ echo "c" > c.txt && git add . && git commit -m "third commit"
$ feature1id=$(git rev-parse --short HEAD)
$ git checkout master
$ git rebase feature1 \
  -ix "git rev-parse --short HEAD > tmp &&  \
  echo 'from: $feature1_id' > tmp && \
  git commit --amend -F tmp"

这是对应的输出:


讨论:

如前所述,我认为您使用 git reflog 是一种更好的解决方案,可以调查从哪个分支上的哪个提交合并到所需的那个。

变基的重点是将提交应用到另一个分支的顶部,就好像那是提交结构一样:

变基会产生linear history

【讨论】:

  • i.stack.imgur.com/8efe9.png 这只是给出了旧头的原始提交ID,对吗?它不会将每个提交的原始 id 放在应用它的位置。
  • 抱歉,给我一个小时
  • @Alex028502 你刚刚做了echo 'from: $feature1_id' &gt; tmp,也没有git rev-parse --short HEAD &gt; tmp
  • @Alex028502 这个想法是其中一个是“根”提交,另一个是更动态的“每个”提交。
  • 当我尝试完全按照您的要求进行操作时,我在git-rebase-todo 中只得到exec git rev-parse --short HEAD &gt; tmp &amp;&amp; echo 'from: ' &gt; tmp &amp;&amp; git commit --amend -F tmp 我不认为该变量会被导出。但无论哪种方式,我都看不到它是如何工作的,因为无论如何它都会将相同的哈希放入每个提交消息中
【解决方案3】:

https://stackoverflow.com/a/54352290/5203563 的基础上,我最终得到了一个看起来像这样的脚本

#! /usr/bin/env bash

set -e

if [[ "$@" != "" ]];
then
    git rebase $@ --exec="$0"
    exit 0
fi

HASH="$(grep -o "\w\{40\}" .git/rebase-merge/done | tail -n1)"

git log --pretty="format:%B%n%nwas $HASH" -n1 | git commit --amend -F -

我想避免使用临时文件。我最初是在两个脚本中完成的,但后来将它们与这个递归的东西合二为一,以便可以轻松共享。我已经打电话给我的git-record,所以如果你去git record HEAD^^^^,它会将当前哈希值放入所有提交中(并在此过程中更改所有哈希值)。

【讨论】:

    【解决方案4】:

    如果你只是使用 rebase 来做一个批次的cherrypick,你可以很容易地自己构建它的pick list,然后用你想要的任何选项来做cherrypicks:

    batchxpickto() {
            local U=${1-@{u\}}      # given branch or default to configured upstream 
            local B=`git symbolic-ref -q --short HEAD`  # branch name to move if any
            local L=`git cherry $U.. | awk /^+/{print\$2}`  # commits to pick if any
            git checkout $U && ${L:+git cherry-pick -x $L}
            ${B:+git checkout -B $B}
    }
    

    像使用 git rebase master 一样使用 batchxpickto master

    真的,我更喜欢Adam's answer,但这是一种替代方法,它的策略可能更普遍有用。

    【讨论】:

    • 我认为自己在 bash 方面相当称职,而 git 一点也不了解那些魔法! {L:+git 位在做什么?你能把我链接到任何 bash 文档吗?
    • @Adam man bash 并查找参数扩展,变量名称周围的大括号允许对扩展进行修饰符,:+ 表示“如果变量设置为非空,则扩展为以下内容”,@987654328如果变量未设置或为空,@ 将扩展为以下内容,省略 : 以省略空测试。所以${1-@{u\}} 是第一个参数(如果已设置),否则@{u} 带有反斜杠是通常的语法转义; ${L:+git cherry-pick -x $L}` 如果没有可樱桃采摘,则扩展为无;等等。这不是特定于 bash 的,这是被低估的标准东西。
    猜你喜欢
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    • 2010-12-25
    • 2012-06-05
    • 2011-07-09
    相关资源
    最近更新 更多