Git - How to selectively apply changes from one branch to another?

醉酒当歌 提交于 2019-12-21 03:39:30

问题


Is it possible to selectively apply changes from one branch to another with Git?

More specifically, I use a public dev branch for GitHub and a private master branch for deployment. When changes are made to one branch they will need to be applied to the other, but some lines of code need to stay different. In my case it's a few css classes and a feed.

I'm new to Git but I've made my research :

  • git merge --no-commit --no-ff can be used followed by a git mergetool to chose what I want in case of a conflict. The problem is that it only works for conflicts Git can't automatically merge, so what I want to stay different gets replaced before I get the chance to use my mergetool.

  • git difftool --cached is useful as it allows me to see the differences, but I need to copy what I want to keep from there and manually replace it with a text editor, as I cannot simply choose and save like I can with mergetool.

  • git cherry-pick seems to apply a specified commit to another, but what I want to stay different may be scattered to different commits, and these commits may not only include what I want to stay different. I cannot see this working unless I make millions of commits that would drive me mad.

Also to be clear, I don't want one branch to become another, what seems to be the case with a merge. I want two separate branches with their respective differences and apply changes from one to the other.

Is there a better workflow that would allow me to keep a development and a deployment version by applying their changes and keeping a few differences? I don't mind using separate repositories or different tools if it leads to a solution.


回答1:


I don't think there is a way to pick parts of a commit from the same file. I would say you need to simply re-factor your code to move such parts in different files.

BTW, if you want to take some files from a commit, you can use cherry-pick with a combination of other commands as explained here.




回答2:


I've also found out about patching :

To create the patch : git diff dev > master.patch

To apply it : patch < master.patch




回答3:


Take advantage of the fact that creating git branches is cheap and need have no effect on the actual content of the working directory.

  1. Check out your source branch dev.
  2. Create a temporary branch. It will point to the same commit that dev does: checkout -b for_master

    Presumably, you know (or can easily find out) which commit before the dev branch is the last one before the changes you (partially) want. In this example, let's say that that commit has the hash 1457B4 ('last before', get it?).

  3. Reset your for_master branch to that commit: git reset 1457B4. (Do not use the --hard switch!)

    Now, you have a working directory containing all the changes that are in dev, but from the POV of the for_master branch, those changes are unstaged and uncommitted (while the dev branch still points to commits that record all the changes, so the work is still safe).

  4. Using interactive staging (git add -p and/or git add -e), create a commit (or more than one, if you like) that contains all, and only, the changes you want to apply to your master branch.

    Make a note of the hash of the last commit (or give it a tag). In this example, I'll say that its hash is C0DA.

  5. Check out master.

  6. Cherry-pick the commit(s) you just made: git cherry-pick 1457B4..C0DA.

    (Note that cherry-picking a range is only available after git version 1.7.2. Otherwise, you'll need to individually cherry-pick all the commits you made in step 4.)

    (Also note that when you cherry-pick a range, the start of the range is the commit before the first one that will actually be picked.)

This process is kind of the inverse of using git checkout -p as mentioned in the selected answer. It might be useful for creating cherry-pick-able commits between two branches that share some code but also have a lot of differences (e.g. between two major versions of a project), and you don't want to have to spend a lot of time ignoring irrelevant files in a call to git checkout -p.

Personally, I've found it convenient to use two different worktree directories for the same repository (one for the source branch and one for the destination) and switch between two command shells, one using the source branch directory (worktree) and the other the destination. But if you aren't comfortable using the git worktree feature, that might not be for you.



来源:https://stackoverflow.com/questions/22367645/git-how-to-selectively-apply-changes-from-one-branch-to-another

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