问题
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 agit 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.
- Check out your source branch
dev
. 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 hash1457B4
('last before', get it?).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 thefor_master
branch, those changes are unstaged and uncommitted (while thedev
branch still points to commits that record all the changes, so the work is still safe).Using interactive staging (
git add -p
and/orgit add -e
), create a commit (or more than one, if you like) that contains all, and only, the changes you want to apply to yourmaster
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
.Check out
master
.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