diff --git a/Library/Homebrew/test/utils/git_spec.rb b/Library/Homebrew/test/utils/git_spec.rb
index 73074226d34a34f671e2196ddf48a02224fa1e0b..09bac00fe2e6f7c709e62083f98874124230a25f 100644
--- a/Library/Homebrew/test/utils/git_spec.rb
+++ b/Library/Homebrew/test/utils/git_spec.rb
@@ -44,6 +44,14 @@ describe Utils::Git do
   let(:files_hash1) { [@h3[0..6], ["LICENSE.txt"]] }
   let(:files_hash2) { [@h2[0..6], ["README.md"]] }
 
+  describe "#cherry_pick!" do
+    it "aborts when cherry picking an existing hash" do
+      expect {
+        described_class.cherry_pick!(HOMEBREW_CACHE, file_hash1)
+      }.to raise_error(ErrorDuringExecution, /Merge conflict in README.md/)
+    end
+  end
+
   describe "#last_revision_commit_of_file" do
     it "gives last revision commit when before_commit is nil" do
       expect(
diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb
index 4180abd88af0d36eaaed357043d39f076f753d1e..168c9ce439d67fb8be1b5249e87d2ca89266ffa2 100644
--- a/Library/Homebrew/utils/git.rb
+++ b/Library/Homebrew/utils/git.rb
@@ -119,5 +119,19 @@ module Utils
       Utils.popen_read(git, "-C", repo, "symbolic-ref", "-q", "--short",
                        "refs/remotes/origin/HEAD").chomp.presence
     end
+
+    # Special case of `git cherry-pick` that permits non-verbose output and
+    # optional resolution on merge conflict.
+    def cherry_pick!(repo, *args, resolve: false, verbose: false)
+      cmd = [git, "-C", repo, "cherry-pick"] + args
+      output = Utils.popen_read(*cmd, err: :out)
+      if $CHILD_STATUS.success?
+        puts output if verbose
+        output
+      else
+        system git, "-C", repo, "cherry-pick", "--abort" unless resolve
+        raise ErrorDuringExecution.new(cmd, status: $CHILD_STATUS, output: [[:stdout, output]])
+      end
+    end
   end
 end