Как можно применить патч-файл, созданный с помощью `git-log -p <filename>`, для создания всех включенных коммитов? - PullRequest
0 голосов
/ 07 июля 2010

Справочная информация: этот вопрос . git apply <patchfile> просто воссоздает файл, но без фиксации истории, что в этом случае было бы желательным. Есть ли переключатель для git-apply для этого? Или есть способ преобразовать файл заплатки в git-am совместимый файл? (В настоящее время git-am жалуется на «Ошибка определения формата исправления»)

Ответы [ 2 ]

1 голос
/ 06 сентября 2011

загляните в git quiltimport. Вы предоставляете каталог, в котором команда находит файл с именем "series". В этом файле вы просто упоминаете имена патч-файлов, в порядке, в котором они будут применяться ». В качестве комментария для фиксации используется текст, предшествующий значению diff в файле, в качестве заголовка используется имя файла (за исключением .patch), и он пытается найти автора в каждом патче, если ничего не найдено, вас просят об этом.

1 голос
/ 09 июля 2010

Вы спросили, так что вот оно.

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

Извлекает (дата / автор / сообщение о коммите / патч) из вывода 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
  }
}
...