【问题标题】:How can a patchfile created with `git-log -p <filename>` be applied to create all the commits included?如何应用使用 `git-log -p <filename>` 创建的补丁文件来创建包含的所有提交?
【发布时间】:2010-07-07 11:28:53
【问题描述】:

背景:this questiongit apply &lt;patchfile&gt; 只是重新创建文件但不提交历史记录,在这种情况下这是可取的。 git-apply 是否有任何开关可以这样做?或者有没有办法将补丁文件转换为git-am 兼容文件? (目前git-am报“补丁格式检测失败”)

【问题讨论】:

  • 如果您有一系列要应用的提交,通常最好创建一个包,或者简单地获取和变基,而不是尝试从 log -p 重新创建提交输出。
  • @Charles 是否也可以用于单个文件的历史记录?这就是上面提到的问题,所以我只是尝试git log -p &lt;filename&gt; &gt; &lt;patchfile&gt; 来获取补丁...
  • git applygit difflog -p 更相反,所以如果不手动拆分输出,我认为这是不可能的(或者不容易,无论如何)。如果您可以在两个存储库之间获得一个捆绑包,那么我认为操纵原始分支以应用于单个文件(例如使用filter-branch)然后重新设置它比摆弄基于文本的补丁要容易得多。跨度>

标签: git history commit patch git-log


【解决方案1】:

你问了,就在这里。

我使用了这个脚本,但它非常脆弱。将其视为灵感,而不是合理的解决方案。

它从git log -p 的输出中提取(日期/作者/提交消息/补丁),然后以相反的顺序运行patch+git add+git apply

可能有一些方法可以自动找出正确的patch_level,但我没有打扰。如果不是全部,请将作者传递给git apply

#!/usr/bin/env ruby

class String
  def shell_escape
    if empty?
      "''"
    elsif %r{\A[0-9A-Za-z+,./:=@_-]+\z} =~ self
      self
    else
      result = ''
      scan(/('+)|[^']+/) {
        if $1
          result << %q{\'} * $1.length
        else
          result << "'#{$&}'"
        end
      }
      result
    end
  end
end

dir1, dir2, *files = ARGV

patchlog = Dir.chdir(dir1){`git log -p #{files.map(&:shell_escape).join(" ")}`}

patches = []
patchlog.each_line{|line|
  if line =~ /\Acommit/
    patches << {}
  elsif line =~ /\A(Author|Date):\s*(.*)/
    patches[-1][$1] = $2
  elsif patches[-1][:diff].nil? and line !~ /\Adiff/
    (patches[-1][:msg] ||= "") << line
  else
    (patches[-1][:diff] ||= "") << line
  end
}

patch_level = 2
skip = 0
dry_run = false

patches.reverse[skip..-1].each{|patch|
  author = patch["Author"].strip
  date = patch["Date"].strip
  msg = patch[:msg].strip
  diff = patch[:diff]

  if dry_run
    puts ["git", "commit", "-m", msg, "--date", date].join(" ")
    next
  end

  Dir.chdir(dir2){
    IO.popen("patch -p#{patch_level}", "w"){|fh|
      fh.puts diff
    }
    system "git", "add", *files
    system "git", "commit", "-m", msg, "--date", date
  }
}

【讨论】:

    【解决方案2】:

    查看git quiltimport。您提供一个目录,该命令在其中找到一个名为“series”的文件。在此文件中,您只需提及补丁文件的名称,以便它将应用它们”。文件中实际差异之前的文本用作提交注释,文件名(减去 .patch)用作标题,它会尝试在每个补丁中找到作者,如果没有找到你会被要求提供。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      • 2014-11-28
      • 1970-01-01
      • 2019-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多