Git 重命名文件的后端口更改

Git 重命名文件的后端口更改,git,cherry-pick,Git,Cherry Pick,我有两个分支:主干、生产。我在主干中发现了一个问题,进行了修复并提交了它,推送了它。现在它已经过测试,我需要将更改作为热修复程序合并到生产分支中。我试着用樱桃采摘。但是,它不起作用,因为修复中的一个或多个更改的文件在之前的一些重构过程中在主干中被重命名,我不想将这些重构引入生产 我不想合并所有内容,但只接受此提交。cherry pick失败,出现“被我们删除”冲突(当然,新文件甚至不存在于生产分支中) 将更改带入旧文件的正确方法是什么?这有点棘手。例如,您可以从一个diff创建一个补丁,并将其应

我有两个分支:主干、生产。我在主干中发现了一个问题,进行了修复并提交了它,推送了它。现在它已经过测试,我需要将更改作为热修复程序合并到生产分支中。我试着用樱桃采摘。但是,它不起作用,因为修复中的一个或多个更改的文件在之前的一些重构过程中在主干中被重命名,我不想将这些重构引入生产

我不想合并所有内容,但只接受此提交。cherry pick失败,出现“被我们删除”冲突(当然,新文件甚至不存在于生产分支中)


将更改带入旧文件的正确方法是什么?

这有点棘手。例如,您可以从一个diff创建一个补丁,并将其应用于旧文件。但为了防止这些问题,我建议将来在生产分支上进行修复,并首先在那里进行测试,然后从生产分支合并到主干中。

我会为此使用好的旧补丁:

git show COMMIT_ID -- old/file/name.txt | patch new/file/name.txt

我也遇到过同样的问题,并试图找到解决办法

我用一系列的回扣解决了这个问题。 我没有做过比这些更进一步的测试,所以使用风险自负

如果您感兴趣,请在github上查看:


若要在分支之间重命名目录,请选择对任意数量的文件所做的更改:

git diff ... | sed -e 's|<old dir>|<new dir>|' | git apply -
git diff…|sed-e的| | | | git apply-
如果:

  • 您期望/希望Git能够检测到主干上文件的移动或重命名,但它没有,并且
  • 您的存储库具有合理数量的文件
。。。然后你应该考虑改变你的Git配置:
$ git config merge.renameLimit 999999
有可能在合并/cherry pick期间,git在找到合适的重命名匹配项之前已经达到了默认的文件检查限制(我认为是400或1000或类似的限制)。提高此限制可能会导致merge/cherry pick在搜索重命名文件时花费更长的时间,但这有助于避免“被我们删除”合并挑战


这应该可以做到,但是如果重命名的文件很小,并且分支之间的更改很明显,您也可以使用
-X rename threshold
设置,例如,使用
-X rename threshold=25%将其从默认的50%降低到

面对同样的问题,我问一位同事他会怎么做,他的即时反应是:

git checkout production

git mv production-filename trunk-filename && git commit -m "Just fooling git"
git cherry-pick trunk-commit
git mv trunk-filename production-filename && git commit -m "Undo the damage"

# Now squash the 3 commits
git rebase -i HEAD~3

这对我来说很有吸引力。

我制作了一个shell脚本,它在猜测文件移动时尝试进行樱桃选择(如果重命名文件本身,则不起作用,仅当您将其移动到另一个文件夹时): 但是:如果提交添加了新文件或自身重命名文件,则当前提交将失败

#!/bin/bash
#
# Attemps to guess file moves (rename of folders) when cherry-pick'ing.
# Gaspard van Koningsveld
#
[ "$1" == "" ] && echo "usage: $0 <commit-hash-to-cherry-pick>" && exit 1
TMP_PATCH_FILE="temp-cherry-pick-patch"
function abort() {
  echo "Aborting"
  "rm" -f "$TMP_PATCH_FILE"
  exit 1
}
function main() {
  echo "Retreiving commit patch..."
  "git" show "$1" > "$TMP_PATCH_FILE" || abort

  echo "Matching renamed files..."
  sedcmds=""
  for oldfile in $("grep" -E '(--- a|\+\+\+ b)' "$TMP_PATCH_FILE" | "cut" -c 7- | "sort" | "uniq"); do
    [ -f "$oldfile" ] && continue
    renamefound=0
    oldfilepart="$oldfile"
    while [ $renamefound -eq 0 ]; do
      possiblefiles=$("git" ls-files "**/$oldfilepart")
      if [ "$possiblefiles" != "" ]; then
        if [ $("wc" -l <<< "$possiblefiles") == "1" ]; then
          echo "  $oldfile > $possiblefiles"
          sedcmds="$sedcmds s|/$oldfile|/$possiblefiles|g;"
          break
        else
          echo "  ERROR: More than one rename possibility found for file $oldfile:"
          echo "$possiblefiles"
          abort
        fi
      fi
      prevoldfilepart="$oldfilepart"
      oldfilepart="${oldfilepart#*/}"
      if [ "$prevoldfilepart" == "$oldfilepart" ]; then
        echo "  ERROR: Could not find rename for $oldfile."
        abort
      fi
    done
  done
  echo "Renaming files in patch..."
  "sed" -i "$sedcmds" "$TMP_PATCH_FILE" || abort
  echo "Applying patch as new commit..."
  "sed" -i "s/^commit /From commit /;s/^Author: /From: /" "$TMP_PATCH_FILE" || abort
  "git" am -3 "$TMP_PATCH_FILE"

  "rm" -f "$TMP_PATCH_FILE"
}
main "$@"
#/bin/bash
#
#尝试在挑选时猜测文件移动(文件夹重命名)。
#加斯帕德·范科宁斯维尔德
#
[“$1”==”]&&echo“用法:$0”&&exit 1
TMP_PATCH_FILE=“temp cherry pick PATCH”
函数中止(){
回声“中止”
“rm”-f“$TMP\u补丁文件”
出口1
}
函数main(){
echo“检索提交修补程序…”
“git”显示“$1”>“$TMP_补丁_文件”||中止
echo“匹配重命名的文件…”
sedcmds=“”
对于$(“grep”-E'(--a |\+\+\+b)“$TMP_PATCH_FILE”|“cut”-c 7-|“sort”|“uniq”);do
[-f“$oldfile”]&继续(&C)
renamefound=0
oldfilepart=“$oldfile”
而[$renamefound-eq 0];则
可能文件=$(“git”ls文件“**/$oldfilepart”)
如果[“$possiblefiles”!=”],则

如果[$(“wc”-l是的,我理解这一点,但是并不总是能够预测热修复会发生什么。我试图通过
格式修补程序
/
应用修补程序
,但它什么也不做(没有错误,也没有更改)。请给出正确使用方法的提示。请查看“git中的重命名处理”部分在这篇文章中,是的,它对我很有用。不过,找到一个更好的解决方案会很有趣,特别是在有几个重命名文件的情况下。这看起来很有希望,但我不知道如何确定COMMIT_ID使用什么以及何时调用此命令。(当我运行
git-rebase-develope
并遇到冲突时,我可以在rebase期间调用它吗?)
COMMIT\u ID
可以是标识提交的任何内容,例如提交哈希、
头、分支名称等。如果您正在重定基址,可能最容易查看历史记录并复制提交哈希。对于其他用户,请注意
重命名阈值
,这包括随着时间的推移所做的所有更改。我对原始重命名进行了合并更改了文件中的两行,但由于在此之后对其进行了大量修改,git在没有降低
重命名阈值的情况下仍然没有检测到文件的相似性。这在我身上起到了作用。我使用了GUI,但遵循了相同的步骤。我花了一分钟才弄清楚这是怎么做的,因此我将列出以下步骤:1.重命名文件/dir目标分支上的分区与源分支和提交相匹配。2.Cherry选择从源分支到目标分支的更改。3.将目标分支上的文件/目录重命名回原来的状态并提交。4.将这3次提交压缩为一次提交。我无法理解这个答案即使它看起来很有希望。如果你有时间,我希望你在这里回答:谢谢!好主意!特别是这条路两边都重新命名了。这很有帮助。谢谢。尽管这个答案看起来很有希望,但我还是无法理解。如果你有时间,我希望你在这里回答:谢谢!