【问题标题】:Git wizard needed - How to merge a branch with a different directory structure?需要 Git 向导 - 如何合并具有不同目录结构的分支?
【发布时间】:2017-07-28 20:37:35
【问题描述】:

从前有两个分支:

--[stable]--hotfix1--h2--h3
       \
        \--[develop]--refactor1--r2--r3

我需要将stable 合并到develop,但我有点麻烦。

develop 已重构为不同的目录结构。并且 Git 无法跟踪更改。

(stable)
    |-app
    |  |-scripts
    |    |-site
    |      |-**ALL THE CODE

(develop)
    |-app
    |  |-modules
    |    |**ALL THE CODE

预期 - 当我运行 git merge 时,git 将 stable 中的修补程序应用到 develop 中的新文件路径。

实际 - Git 将带有修补程序的文件标记为“被我们删除”,因为它们具有旧的目录结构。

如何让 Git 将 stable 中的修补程序应用到 develop 中的新目录结构?

【问题讨论】:

  • 如果这是一次性操作,我可能只是从每个更改的文件中获取差异并将它们应用到新目录结构中的相应文件,而不是尝试使用内置的 git 机制.
  • @merlin2011 是的,这听起来是个不错的选择。我会试试这个家伙的答案:stackoverflow.com/a/22159810/2954463
  • Git 似乎不适用于分支中重新构建文件夹的情况,尤其是它无法在不同分支上维护新文件。考虑这种情况:我们在开发分支上提交一个新文件“app/modules/1.sh”,然后将其挑选到稳定分支。 Git 将新文件合并到相同的路径(app/modules/1.sh),但我们希望路径应该是“app/scripts/site/1.sh”。此外,我们不能重命名它并提交,因为稳定分支稍后会集成到开发分支中。我希望是否也有解决方案。谢谢。

标签: git github merge


【解决方案1】:

stable 的目录结构更改为匹配develop(在提交中)可能会起作用,然后您可以将它们合并在一起。我只是手动执行此操作(使用文件浏览器),但如果您真的很想在整个任务中使用 git 命令,您可以在 develop 上找到更改目录结构的提交,将其挑选到 @987654324 @,然后合并可能会正确应用(可能存在一些合并冲突)。

【讨论】:

    【解决方案2】:

    您可以通过模拟与已重命名的所有内容的合并来帮助 Git。以 Bash 为例,

    # Mark this as the branch to be merged.
    git update-ref --stdin <<<'create MERGE_HEAD stable'
    printf '%s\t\t%s\n' $(git rev-parse MERGE_HEAD) "branch 'stable'" |
    >$(git rev-parse --git-dir)/MERGE_MSG git fmt-merge-msg \
      $([[ $(git config --bool merge.log) = true ]] && echo --log)
    # This outputs a tree object with some paths transformed.
    refactor-tree() {
      (
        index1= index2=
        trap 'rm -f "${index1}" "${index2}"' 0
        index1=$(mktemp) index2=$(mktemp)
        GIT_INDEX_FILE=${index1} git read-tree "$@"
        GIT_INDEX_FILE=${index2} git read-tree --empty
        GIT_INDEX_FILE=${index1} git ls-files -s -z |
        while IFS=$'\t' read -d '' -r info file; do
          [[ ${file} = app/scripts/site/* ]] && file=app/modules/${file#*/*/*/}
          printf '%s\t%s\0' "${info}" "${file}"
        done |
        GIT_INDEX_FILE=${index2} git update-index --index-info
        GIT_INDEX_FILE=${index2} git write-tree
      )
    }
    # Update the index for the 3-way merge.
    git read-tree -m --aggressive -u \
      $(refactor-tree $(git merge-base MERGE_HEAD HEAD)) \
      $(git write-tree) \
      $(refactor-tree MERGE_HEAD)
    # Resolve the merge.
    git merge-index -o git-merge-one-file -a
    # Commit the results.
    git commit
    

    以上内容已在这样创建的演示存储库上进行了测试:

    git init
    mkdir -p app/scripts/site
    cat >app/scripts/site/README.md <<EOF
    Hello, world!
    =============
    EOF
    git add app/scripts/site/README.md
    git commit -m 'base'
    git checkout -b stable
    sed -i -e '1s/w/W/' app/scripts/site/README.md
    git add app/scripts/site/README.md
    git commit -m 'hotfix'
    git checkout master -b develop
    git mv app/scripts/site app/modules
    rm -rf app/scripts
    git commit -m 'refactor'
    cat >>app/modules/README.md <<EOF
    blah blah blah
    EOF
    git add app/modules/README.md
    git commit -m 'blah'
    

    请注意,如果您删除 ============= 行,合并将由于该文件中的冲突而失败,但它会像往常一样获取上下文标记。您可以手动解决它并尝试再次提交。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 2012-03-23
      • 2021-03-11
      • 2021-06-10
      • 2010-12-07
      • 2010-09-20
      相关资源
      最近更新 更多