2012-03-19 61 views
17

我有兩個分支:主幹,生產。我在後備箱裏發現了一個問題,做了修理並將其付諸實施,並將其推出。現在已經過測試,我需要將更改合併到生產分支中作爲熱修復。我嘗試使用櫻桃挑選。但是它不起作用,因爲在我不想投入生產的一些重構過程中,修正中的更改文件在主幹中被重命名。從重命名文件的backport更改

我不想合併的一切,但只拿這個承諾。櫻桃挑選失敗並且「被我們刪除」衝突(當然,新文件甚至從未在生產分支中存在)。

什麼是把變成舊的文件正確的方法是什麼?

回答

11

我會用好老補丁這樣的:

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

是的,它適用於我。然而,找到更好的解決方案會很有趣,特別是在有多個重命名文件的情況下。 – kan 2012-03-19 18:41:22

0

這有點棘手。例如,您可以從差異創建補丁並將其應用於舊文件。但是爲了避免這些問題,我建議在生產分支上進行修復,然後在那裏進行測試,然後從生產合併到主幹。

+0

是的,我知道,但是並不總是可以預測進入hot-fix的內容。我試圖通過'format-patch' /'apply-patch'來完成,但它什麼也沒做(沒有錯誤,也沒有改變)。請給出適當的使用方法。 – kan 2012-03-19 15:42:38

+2

查看本帖子中的「重命名git處理」一節http://blogs.atlassian.com/2011/10/confluence_git_rename_merge_oh_my/ – ralphtheninja 2012-03-19 16:03:44

0

我遇到同樣的問題,並試圖找到一個解決方案。

我解決了用底墊的序列。 我沒有做過進一步的測試,所以請自行承擔風險!

如果your're興趣看看它在GitHub上:

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

2

櫻桃採摘修改任意數量的文件,目錄中的情況下,部門之間的重新命名:

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

如果:

  • 您預期/希望的Git會檢測到移動或重命名的樹幹上的文件,但它沒有,
  • 你的版本庫文件的合理數量

...那麼你絕對應該考慮改變你的混帳配置是這樣的:

$ git config merge.renameLimit 999999 

這是可能的合併/摘櫻桃時,Git是擊中默認文件檢查限制(我認爲這是400或1000或類似的東西)之前,它是能夠找到合適的命名比賽。提高此限制可能會導致合併/櫻桃選擇花費更長時間來搜索您的重命名文件,但它可以幫助避免「被我們刪除」合併挑戰。

這應該做的伎倆,但如果你重命名的文件很小,分支機構之間的變化是顯著,你也可以用-X rename-threshold設置,例如玩使用-X rename-threshold=25%將其從默認的50%降低。

+2

關於其他用戶的'rename-threshold'的說明 - 這包括所有隨時間的變化。我有一個合併的地方,原來的重命名改變了文件中的兩行,但是由於它已經在*那個點之後進行了大量修改,所以git在沒有降低'rename-threshold'的情況下仍然沒有檢測到文件相似性。 – zebediah49 2016-06-02 18:36:56

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 

工作就像對我的魅力。

+2

這工作從我。我使用了GUI,但是遵循了相同的步驟。 我花了一分鐘的時間來弄清楚這是做什麼,所以我會列出步驟: 1.重命名目標分支上的文件/目錄以匹配源分支並提交。 2. Cherrypick從源分支到目標分支的更改。 3.將目標分支上的文件/目錄重命名爲它們原來的狀態並提交。 4.將這3個提交壓縮爲一個提交。 – Tolli 2017-08-29 20:05:59

0

我做了一個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 "[email protected]"