How to selectively merge or pick changes from anot

2018-12-31 06:35发布

I'm using git on a new project that has two parallel -- but currently experimental -- development branches:

  • master: import of existing codebase plus a few mods that I'm generally sure of
  • exp1: experimental branch #1
  • exp2: experimental branch #2

exp1 and exp2 represent two very different architectural approaches. Until I get further along I have no way of knowing which one (if either) will work. As I make progress in one branch I sometimes have edits that would be useful in the other branch and would like to merge just those.

What is the best way to merge selective changes from one development branch to another while leaving behind everything else?

Approaches I've considered:

  1. git merge --no-commit followed by manual unstaging of a large number of edits that I don't want to make common between the branches.

  2. Manual copying of common files into a temp directory followed by git checkout to move to the other branch and then more manual copying out of the temp directory into the working tree.

  3. A variation on the above. Abandon the exp branches for now and use two additional local repositories for experimentation. This makes the manual copying of files much more straightforward.

All three of these approaches seem tedious and error-prone. I'm hoping there is a better approach; something akin to a filter path parameter that would make git-merge more selective.

24条回答
像晚风撩人
2楼-- · 2018-12-31 07:01

There is another way do go:

git checkout -p

It is a mix between git checkout and git add -p and might quite be exactly what you are looking for:

   -p, --patch
       Interactively select hunks in the difference between the <tree-ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree-ish> was specified, the index).

       This means that you can use git checkout -p to selectively discard
       edits from your current working tree. See the “Interactive Mode”
       section of git-add(1) to learn how to operate the --patch mode.
查看更多
墨雨无痕
3楼-- · 2018-12-31 07:01

I know I am a little late but this is my workflow for merging selective files.

#make a new branch ( this will be temporary)
git checkout -b newbranch
# grab the changes 
git merge --no-commit  featurebranch
# unstage those changes
git reset HEAD
(you can now see the files from the merge are unstaged)
# now you can chose which files are to be merged.
git add -p
# remember to "git add" any new files you wish to keep
git commit
查看更多
不再属于我。
4楼-- · 2018-12-31 07:03

I had the exact same problem as mentioned by you above. But I found this git blog clearer in explaining the answer.

Command from the above link:

#You are in the branch you want to merge to
git checkout <branch_you_want_to_merge_from> <file_paths...>
查看更多
伤终究还是伤i
5楼-- · 2018-12-31 07:05

I found this post to contain the simplest answer. Merely do:

$ #git checkout <branch from which you want files> <file paths>

Example:

$ #pulling .gitignore file from branchB into current branch
$ git checkout branchB .gitignore

See the post for more info.

查看更多
大哥的爱人
6楼-- · 2018-12-31 07:06

I had the exact same problem as mentioned by you above. But I found this clearer in explaining the answer.

Summary:

  • Checkout the path(s) from the branch you want to merge,

    $ git checkout source_branch -- <paths>...
    

    Hint: It also works without -- like seen in the linked post.

  • or to selectively merge hunks

    $ git checkout -p source_branch -- <paths>...
    

    Alternatively, use reset and then add with the option -p,

    $ git reset <paths>...
    $ git add -p <paths>...
    
  • Finally commit

    $ git commit -m "'Merge' these changes"
    
查看更多
有味是清欢
7楼-- · 2018-12-31 07:07

If you don't have too many files that have changed, this will leave you with no extra commits.

1. Duplicate branch temporarily
$ git checkout -b temp_branch

2. Reset to last wanted commit
$ git reset --hard HEAD~n, where n is the number of commits you need to go back

3. Checkout each file from original branch
$ git checkout origin/original_branch filename.ext

Now you can commit and force push (to overwrite remote), if needed.

查看更多
登录 后发表回答