如何自动删除取消自己的提交? [英] How to automagically remove commits that cancel themselves out?

查看:57
本文介绍了如何自动删除取消自己的提交?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有很多提交的开发分支.这些提交包括真实的"更改(例如添加功能)以及临时更改(例如在一次提交中添加测试代码,然后在以后的提交中将其删除).

I have a development branch with many commits. These commits include "real" changes (e.g. add a feature) as well as temporary changes (e.g. add test code in one commit, then remove it in a later commit).

这个分支的真正变化正在逐渐添加到 master 中.每次添加后,我都会在新的 master 上重新设置 develoment 分支.随着每个周期,开发分支和主分支之间的差异越来越小.但是,重新定位的开发分支包含所有原始(现在重新定位)提交.其中一些提交现在具有零净效应.

The real changes from this branch are being gradually added into the master. After each addition, I rebase the develoment branch on the new master. With each cycle, difference between the development branch and the master is getting smaller. However, the rebased development branch contains all original (now rebased) commits. Some of these commits now have zero net effect.

简单例子:

DEV_BRANCH
    Commit ...
    Commit D: Remove all test code from f.cpp
    Commit ...
    Commit C: Add new feature to f.cpp
    Commit ...
    Commit B: Add more test code to f.cpp
    Commit A: Add some test code to f.cpp
    Commit ...
MASTER
    Commit X: Add new feature to f.cpp
    Commit ...

此时,从commit C改成f.cpp已经in master as commit X,并且commit A+B+D 组合时没有变化到f.cpp.换句话说,分支和主节点之间的差异对于文件 f.cpp 没有任何显示.

At this point, change to f.cpp from commit C is already in the master as commit X, and commits A+B+D when combined have no change to f.cpp. In other words, diff between the branch and the master shows nothing for file f.cpp.

(实际上,提交 A、B、C 和 D 也可能包括对其他文件的更改.)

(In reality, commits A, B, C, and D may include changes to other files as well.)

有没有办法在变基期间或其他情况下自动简化开发分支中的提交?

在上面的简单示例中,是否可以删除提交C(更改已经合并到master,因此现在空")并且还提交ABD(组合时无变化)自动?

In the above simple example, is it possible to remove commit C (with change already merged to master hence now "empty") and also commits A, B, and D (no change when combined) automatically?

在更复杂的情况下,当对 f.cpp 的提交也修改其他文件时,是否可以从开发分支的提交中自动删除对文件 f.cpp 的更改(以简化它们)但保留提交如果它们包含对其他文件的更改?

In a more complicated scenario when the commits to f.cpp modify other files as well, is it possible to remove changes to file f.cpp automatically from the commits in the development branch (to simplify them) but leave the commits present if they include changes to other files?

重新表述,如果将开发分支中所有提交的所有更改应用于文件导致文件与主文件中的文件相同,是否可以从开发分支提交中删除对此文件的更改?(我确实意识到这可能会导致副作用,如果对其他文件的更改需要与对没有实际影响的文件的更改同步完成.但是,这在我的场景中不是问题,因为我不需要樱桃- 从开发分支中选择任何中间状态.)

Rephrased, if applying all changes to a file from all commits in the development branch results in a file identical to the one in the master, is it possible to prune changes to this file from the development branch commits? (I do realize this may lead to side-effects if changes to other files need to be done in sync with those to the file that has no net effect. However, this is not a problem in my scenario because I do not need to cherry-pick any intermediate state from the development branch.)

推荐答案

我认为对于您的特定用例,有几个相当简单的解决方案,它们首先考虑了欺骗是如何生成的.

I think that there are a couple of fairly simple solutions for your particular use-case that take into account how the dupes are generated in the first place.

>

解决方案 1:对于发散分支上的少量提交

假设您在 git rebase --interactive 模式下的 dev 中有以下一组提交:

Let's say you have the following set of commits in dev shown in git rebase --interactive mode:

pick bf45b13 Add feature X
pick b1f790f Cleanup feature X
pick 40b299a Add feature Y

现在您决定将 40b299a 选为 master.

Now you decide to cherry-pick 40b299a into master.

问题是当你重新设置 dev 时的新提交将是空的.我建议为将来的 rebase 做 git rebase -i master.然后你可以删除你从选择中挑选的行,只留下你想要的提交.

The problem is that the new commit when you rebase dev will be empty. I would recommend doing git rebase -i master for future rebases. You can then delete the lines that you cherry picked from the selection, and be left only with the commits that you want.

由于您想自动"执行此操作,您可以制作自己的 git 脚本来同时执行cherry-pick 和 rebase,从而在将 dev 添加到 master 时消除正确的提交.

Since you want to do this "automagically", you can make your own git script to do a simultaneous cherry-pick and rebase, eliminating the correct commit from dev while adding it to master.

如果您调用以下脚本类似于 git-transfer,并将其添加到您的 PATH 某处,您可以将其调用为 git transfer dev master commit[...]:

If you call the following script something like git-transfer, and add it to your PATH somewhere, you can invoke it as git transfer dev master commit [...]:

#!/bin/bash

usage() {
    echo "Usage: git transfer from-branch to-branch commits [...]"
    if [ -n "${1}" ]
    then
        echo
        for line; do echo "${line}"; done
    fi
    exit 1
}

FROM="$(git rev-parse --abbrev-ref "${1}")"
[ -z "${FROM}" ] && usage 'from-branch must be a valid branch name' || shift
TO="$(git rev-parse --abbrev-ref "${1}")"
[ -z "${TO}" ] && usage 'to-branch must be a valid branch name' || shift

ORIGINAL="$(git rev-parse --abbrev-ref HEAD)"

if [ "${ORIGINAL}" == "${TO}" ]
then
    echo "Already on branch ${TO}"
else
    echo "Switching from ${ORIGINAL} to ${TO}"
    git checkout "${TO}" || exit
fi

while [ $# -gt 0 ]
do
    for COMMIT in "$(git rev-parse "${1}" | grep '^[^^]')"
    do
        echo "Moving ${COMMIT} to ${TO}"
        git cherry-pick "${COMMIT}"
        echo "Removing ${COMMIT} from ${FROM}"
        EDITOR="sed -i '/^pick $(git rev-parse --short ${COMMIT})/ d'" git rebase -i "${TO}" "${FROM}"
    done
    shift
done

if [ "${ORIGINAL}" != "${TO}" ]
then
    echo "Switching back to ${ORIGINAL} from ${TO}"
    git checkout "${ORIGINAL}"
fi

脚本接受将被重新定位的from"分支的名称,将被挑选到的to"分支的名称,以及提交列表、提交范围等.它基于大量关于此问题answer(对于循环也是这个answer).

The script accepts the name of the "from" branch that will be rebased, the name of the "to" branch that will be cherry-picked into, and a list of commits, commit ranges, etc. It is based heavily on the ideas proposed in this question and answer (Also this answer for the loop).

此解决方案适用于少量提交(最有可能一次提交一次)以及出现明显分歧的分支.

This solution is suitable for small numbers of commits (one at a time most likely) as well as for branches that have diverged significantly.

解决方案 2:对于单个时间线上的大量提交

在您描述的用例中,您定期将 dev 变基到 master 上,因此 dev 一直有效地领先于 master.下一次,不要选择单个提交到 master,而是执行以下操作:

In the use case you described, you periodically rebase dev onto master, so dev is effectively ahead of master all the time. Next time, instead of picking individual commits onto master, do the following:

  1. 启动交互式变基
  2. 将您想要的提交移到列表的开头
  3. 完成变基
  4. 将 master 移动到您想要的最后一次提交.

这种方法将使您免于任何重复,并且可能是您能做的最简单的事情.请注意,虽然 dev 会不断地重新定位,但 master 只会用这种方法快进.

This approach will save you from having any duplication at all and is probably the simplest thing you can do. Note that while dev will constantly be rebased, master will only fast forward with this approach.

这篇关于如何自动删除取消自己的提交?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆