0

Unfortunately dev & master are developed separately from a few weeks ago.many files are created or updated on branch dev and i want have this changes and its history on master branch for just some files.

how cherrypick(or any transfer way) all commits that change specific files from dev branch to master branch?

I think it should be get log of commits for all those files and sort them by date then cherrypick but it takes a lot of time.

  • I am sorry, your question is not really clear to me… From [your comment](https://stackoverflow.com/questions/76296076/cherrypick-all-commits-that-change-specific-filestransfer-changes-its-history#comment134546026_76297736) I assume squash-merging (which I’d probably do) is not acceptable for you (why actually?). So do you want to 1. cherry-pick _all_ changes from commits that touch specified files (i.e. include changes to other files), or 2. cherry-pick just the changes to the specified files? Have you tried to find a solution on other pages, e.g. https://stackoverflow.com/q/5717026/711006? – Melebius Jun 08 '23 at 06:28

2 Answers2

1

I'm not aware of a way of doing this in git directly, but you could use git log to list all the relevant commits, and use some shell scripting to apply them on master.

The first order of business is to find where the master and dev branches diverge. If dev is rebased on top of master it's easy (that point is simply master), but if not, you can use git merge-base to find it.
Once you've found it, you can use git log to list all the relevant commit hashes in reverse order and pipe them to git cherry-pick using xargs.

Running on the master branch:

git log `git merge-base master dev`..dev --reverse --format='%H' -- x.txt | xargs git cherry-pick
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • `git rev-list --reverse | git cherry-pick --stdin` Option `--stdin` is undocumented but used in [an example](https://git-scm.com/docs/git-cherry-pick#Documentation/git-cherry-pick.txt-codegitrev-list--reversemaster--READMEgitcherry-pick-n--stdincode). – phd May 20 '23 at 16:52
0

Here's an alternate approach that has some down-sides, so consider carefully if it meets your needs:

From the restriction of 'specific files', I believe that you care only about the state of files, not necessarily what the logical change is (i.e. this file change because of bug-fix #149). That is, I only want these specific files to match the contents in the dev branch.

Remember that a git commit isn't a set of changes, it's a point-in-time snapshot of the files when that commit was made. All the diff output between main, dev, 93ab34de and 7752fbe isn't saved in the commit object, all those diffs are computed dynamically when you run the git diff command. Replaying those commits (cherry-picking) isn't about getting the file to the same point, it's about bringing that history -- those points in time combined with the rationale of why these changes were made -- into the main branch.

After the cherry-pick, the narrative of how main got to its current state includes commit messages that discuss bug-fix #149, feature Y, and code-refactor-for-clarity as well as the state of the files after each of these logical commits was made. If you need to revert main, the commit messages help you quickly understand the context of why these files were changed. For example, commit 7752fbe can be targeted because feature Y has a performance regression.

But in this question, the request seems to worry more about the state of specific files, rather than bringing specific bits of history forward. The history is about a set of files. The request seems to be "I need this end state", rather than the change (after all, the change may involve more files than the ones we've named).

A solution, then:

  1. from main, create and enter a new branch (for hygiene); call it surgery
  2. git checkout dev -- [file1, file2, file3]
  3. test to make sure your code is now as desired
  4. create a new commit; this captures the state of main + those files you've checked out from dev.
  5. go back to main and merge your surgery commit.

Conceptually, surgery is similar to a squash-merge of all those cherry-picked commits.

The downside of this, and any squash merge, is that you lose the metadata around the code development. Git is no longer tracking the individual commits around the intermediate changes. A kludge here would be to include git log main..dev as part of the surgery commit message.

A separate downside is confirming that the changes are complete. When commit 'feature Y' was made, it was a logical set of changes that git-author made, and could describe the rationale for those changes. Presumably he/she/they had tested the quality of the change. That is, they verified that everything worked at each point-in-time of each commit. If a change of file1 implied an update of file2, then their commit includes that. In our git checkout approach, we could miss such repercussions. As such, be very careful in validating functionality of the entire code-base when making your surgery commit.

Hefeweizen
  • 41
  • 2