How can a patchfile created with `git-log -p <filename>` be applied to create all the commits included?

强颜欢笑 提交于 2019-12-13 07:29:41

问题


Background: this question. git apply <patchfile> just recreates the file but without committing the history, which in this case would be desireable. Is there any switch for git-apply to do so? Or is there a way to convert the patchfile into a git-am compatible file? (Currently, git-am complains "Patch format detection failed")


回答1:


You asked, so here it is.

I used this script, but it's all rather fragile. Treat it an as inspiration, not as a reasonable solution.

It extracts (date / author / commit message / patch) from output of git log -p, and then runs patch+git add+git apply for all, in reverse order.

There's probably some way of automatically figuring out correct patch_level, but I didn't bother. And pass author to git apply if it's not all you.

#!/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:


look into git quiltimport. You provide a directory where the command finds a file called "series". In this file you simply mention the names of the patchfiles, in order which it will apply them". The text prior to the actuall diff in the file is used as commit comment, the filename (minus the .patch) is used as headline, and it tries to find the author in each patch, if none are found you get asked for it.



来源:https://stackoverflow.com/questions/3194240/how-can-a-patchfile-created-with-git-log-p-filename-be-applied-to-create-al

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!