Изменения в backport из переименованного файла

У меня два ветки: багажник, производство. Я нашел проблему в багажнике, исправил и совершил его, нажал. Теперь он был протестирован, и мне нужно объединить изменения в производственную отрасль в качестве исправления. Я стараюсь использовать вишневый кикер. Однако это не работает, потому что измененный файл в исправлении был переименован в соединительную линию ранее во время некоторого рефакторинга, который я не хочу приводить в действие.

Я не хочу слить все, но возьму только эту фиксацию. Вишневый выбор терпит неудачу с конфликтом "удалены нами" (конечно, новый файл никогда не существовал в производственной ветки).

Каков правильный способ внесения изменений в старый файл?

Ответы

Ответ 1

Я использовал бы старый старый патч для этого:

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

Ответ 2

Если:

  • Вы ожидали/надеялись, что Git обнаружит перемещение или переименование файла на внешней линии, но это не так, и
  • В вашем репозитории имеется разумное количество файлов

... тогда вам обязательно нужно будет изменить конфигурацию Git следующим образом:

$ git config merge.renameLimit 999999

Возможно, что во время слияния/вишни, Git бьет по умолчанию контрольный лимит файла (я думаю, это 400 или 1000 или что-то в этом роде), прежде чем он сможет найти подходящее совпадение переименования. Увеличение этого предела может привести к тому, что слияние/выбор вишни займет больше времени, пока он будет искать ваш переименованный файл, но он может помочь избежать проблем с "слиянием".

Это должно сделать трюк, но если ваш переименованный файл был небольшим и изменения между ветвями значительны, вы также можете играть с настройкой -X rename-threshold, например. опустив его с 50% по умолчанию с помощью -X rename-threshold=25%.

Ответ 3

Столкнувшись с той же проблемой, я спросил коллегу, что он будет делать, и его мгновенный ответ:

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

Работала как прелесть для меня.

Ответ 4

Чтобы чередовать изменения в любом количестве файлов, в случае переименования каталога между ветвями:

git diff ... | sed -e 's|<old dir>|<new dir>|' | git apply -

Ответ 5

Это довольно сложно. Например, вы можете создать патч из diff и применить его к старому файлу. Но в будущем, чтобы предотвратить эти проблемы, я бы рекомендовал сделать исправления в производственной ветки и сначала проверить ее там, а затем объединить с производством в магистраль.

Ответ 6

Я испытываю ту же проблему и пытаюсь найти решение.

Я решил, используя последовательность переустановок. Я не проводил никаких дальнейших испытаний, кроме тех, которые используют на свой страх и риск!

Если вам интересно посмотреть на github:

https://github.com/fraschfn/cherry-pick

Ответ 7

Я сделал оболочку script, которая пытается сделать вишневый выбор при угадывании перемещения файла (он не работает, если вы переименовали сам файл, только если вы переместили его в другую папку): Однако: в настоящий момент это не удастся, если коммит добавляет новые файлы или сам переименовывает файлы.

#!/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 "[email protected]"