简体   繁体   English

是否可以在不使用交互式重新设置基础的情况下重新设置和编辑git commit?

[英]Is it possible to rebase and edit a git commit without using interactive rebase?

I use git rebase -i on a regular basis and I was hoping to find a way to speed up the process. 我定期使用git rebase -i,希望能找到一种方法来加快此过程。

For example, I want to edit the 2nd-newest commit in my git history. 例如,我要编辑我的git历史记录中的第二次最新提交。 I could use: 我可以使用:

git rebase -i HEAD~2

... and then set the commit to 'e' and save ...然后将提交设置为“ e”并保存

I would prefer to be able to do something like: 我希望能够执行以下操作:

git rebase edit HEAD~2

Can rebase be used in this way? 可以以这种方式使用rebase吗?

Not directly, but you could write a script to do this, because git rebase -i invokes two different editors. 不是直接的,但是您可以编写脚本来执行此操作,因为git rebase -i调用两个不同的编辑器。 More precisely, it first invokes the sequence editor on the set of pick commands, and then invokes the core editor for files for which you have changed pick to either edit or reword . 更准确地说,它首先在pick命令集上调用序列编辑器 ,然后为您已将pick更改为editreword文件调用核心编辑器

Thus, by setting the sequence editor to a different command than your normal interactive editor, you can make an interactive rebase interact less than usual. 因此,通过将序列编辑器设置为与普通交互式编辑器不同的命令,可以使交互式库的交互比平时少。 (You can also tweak your core editor setting so that it does not interact at all, even when behaving interactively.) (您也可以调整核心编辑器设置,以使它根本不交互,即使是交互行为也是如此。)

The sequence editor is taken from $GIT_SEQUENCE_EDITOR if set, or git config --get sequence.editor , or using the standard fallback. 如果设置了序列编辑器,则从$GIT_SEQUENCE_EDITOR ,或者从git config --get sequence.editor ,或者使用标准后备。 The core editor is taken from $GIT_EDITOR if set, or git config --get core.editor , or using the standard fallback. 如果设置了核心编辑器,则使用$GIT_EDITORgit config --get core.editor ,或使用标准后备。

The standard fallback is to use $VISUAL , or if that is not set, use $EDITOR , or if that is not set, use a compiled-in default (often vi or vim ). 标准的后备方法是使用$VISUAL ,或者,如果未设置,则使用$EDITOR ,或者,如果未设置,则使用嵌入式默认值(通常是vivim )。

Putting this all together (and using bits from git-sh-setup ), I wrote the following completely untested script to reword (not amend) commits. 将所有这些放在一起(并使用git-sh-setup ),我编写了以下完全未经测试的脚本来重新编写(而不是修改)提交。 It should be obvious how to rework it to allow amending (editing) commits. 很明显,如何进行修改以允许修改(编辑)提交。

#! /bin/sh
#
# git-reword: use git rebase -i to reword one particular commit

SUBDIRECTORY_OK=Yes
USAGE="<commit>"

. $(git --exec-path)/git-sh-setup

case $# in
1) ;;
*) usage;;
esac

rev=$(git rev-parse "$1") || exit 1
# We now know which commit to reword; find it relative to HEAD,
# and find the parent argument to pass to "git rebase -i".

# If we wanted to allow multiple rewords we would need to sort
# them topologically so as to find the correct parent argument.
# "git rev-list --no-walk --topo-order <rev> <rev> ..." can do this
# now, but watch out, older rev-lists do not apply the sort if there
# are specific revisions listed on the command line.

if ! git merge-base --is-ancestor $rev HEAD; then
    fatal "$1 is not an ancestor of HEAD, cannot reword by rebasing"
fi
# Is it the root commit?  Are there merges between it and HEAD?
if parent=$(git rev-parse -q --verify ${rev}^); then
    # it has a (first) parent, so don't need --root
    nmerge=$(git rev-list --count --merges $parent..HEAD)
else
    # it has no first parent, so use --root instead
    parent="--root"
    nmerge=$(git rev-list --count --merges HEAD)
fi

# Refuse to run if there are merges.  This is partly a matter
# of taste since we could attempt to combine -i and -p (since
# we are not deleting any pick lines) but it's definitely safer
# to refuse to re-do merges: we don't know if there are evil
# merges, for instance, nor want to force manual re-merges.

if [ $nmerge -gt 0 ]; then
    [ $nmerge -gt 1 ] && msg="are $nmerge merges" || msg="is a merge"
    fatal "Cannot reword: there $msg in the way."
fi

require_clean_work_tree "reword" "Please commit or stash them."

# If we allowed merges, the pick line we want might not be
# the very first pick command; but we don't, so it is, so
# that makes our "editor" pretty easy.

# If we want to allow multiple reword hashes, change this
# to write a script that reads each line and matches SHA-1s
# (we need to expand them a la git-rebase--interactive and
# then match them against the IDs we'd like to reword).

TF=$(mktemp)
trap "rm -f $TF" 0 1 2 3 15
cat << END > $TF
#! /bin/sh
# change first line from "pick ..." to "reword ..."
# copy the remaining lines unchanged
sed -e '1s/^pick/reword/'
END
chmod +x $TF
GIT_SEQUENCE_EDITOR=$TF git rebase -i $parent

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM