如何应用使用 `git-log -p` 创建的补丁文件来创建包含的所有提交?

发布于 2024-09-08 08:10:32 字数 317 浏览 8 评论 0原文

背景: 这个问题。 git apply只是重新创建文件,但不提交历史记录,在这种情况下这是理想的。是否有任何开关可以让 git-apply 执行此操作?或者有没有办法将补丁文件转换为 git-am 兼容文件? (目前,git-am 抱怨“补丁格式检测失败”)

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")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

貪欢 2024-09-15 08:10:32

你问了,所以就在这里。

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

它从 git log -p 的输出中提取(日期/作者/提交消息/补丁),然后运行 ​​patch+git add+< code>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 << "'#{
amp;}'"
        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
  }
}

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 << "'#{
amp;}'"
        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
  }
}
半岛未凉 2024-09-15 08:10:32

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文