WoJ
WoJ

Reputation: 29977

Is it possible to move files or file changes between branches?

Summary: I forgot to switch branches when developing and would like to move the files/changes to the appropriate branch.

Details: I have two files A and B which are initially in master. I then created a branch branch1 to make some breaking changes in file A.

While developing these changes I also modified B and created a file C. The problem is that I now realize I made a mistake with branching and that

All of them are now commited in branch1.

The commits were pushed to a remote repository but it does not matter that much, I can have the other developer clone the repo (as opposed to fetch).

What is the general methodology to recover in such a case, ie. to move files or changes between branches?

Upvotes: 4

Views: 2763

Answers (4)

MayeulC
MayeulC

Reputation: 1848

When this happens to me, I usually use the stash to move changes around branches. Assuming you didn't commit anything:

  • Only add and commit A to the branch it belongs to
  • git stash, or alternatively git stash save 'useful message to remember what I was doing' to save your changes
  • git checkout -b branch2
  • git stash apply to apply your changes to B
  • add and commit B
  • git checkout master
  • add file C which shouldn't have changed nor moved while performing these commands, unless there is another file named C.

Since you already commited everything, I simply suggest you to undo it; this shouldn't be a problem unless you shared your work with someone else.

git reset HEAD^

should perform this, leaving you with the files as if they hadn't been commited to the branch. You can now perform the above operations.

If you already shared your work with the rest of the world, however, I wouldn't alter the history, unless you can coordinate everyone involved to retrieve your changes.

Upvotes: 0

user4046031
user4046031

Reputation:

  • You can cherry-pick commit from one branch to another (I don't know structure of your commits, if C file is in one commit and changes in B in other). Copy SHA1 hash code of commit, checkout to branch where you need those changes and
git cherry-pick <SHA1_hash>
  • Another option is to make patch
git diff <starting_commit_hash> <ending_commit_hash> > changes.patch
git checkout <branch>
git apply --check changes.patch
git apply -p1 < changes.patch
rm changes.patch
  • If you want diff of particular file then
git diff <starting_SHA1_hash> <ending_SHA1_hash> -- path/file > changes.patch
  • if you have some images or some other files that are essentially binary use
git diff --full-index --binary <starting_SHA1_hash> <ending_SHA1_hash> > changes.patch
    1. Create branch2 from master and use patch for file B to apply it
    1. If your commits are dirty (have changes from files A, B, C) then you need to create new branch from master and apply changes of A file to it.
      • If your commits are gradual then you can do interactive rebase and omit unwanted commits (don't do this if you pushed this branch to remote beacuse it rewrites history) or even revert them (but then log isn't some beauty)
    1. Apply patch for file C to master
    1. When you have all changes applied to correct branches do hard reset on your starting branch to commit that represent desirable state or delete it
git reset --hard <SHA1_hash> or git branch -D <branch>

Upvotes: 0

jeremykenedy
jeremykenedy

Reputation: 4275

I am thinking that you are going to want to look at the git log using the following command:

sudo git log

Then, you will want to checkout/revert the hash of a previous commit that was done where you edited a file but not others yet and that is what you want in branch2. To checkout/revert to the old commit use the following command:

sudo git revert THELONGNUMERICHASHCODEGOESHERE

e,g. sudo git revert 102b78f76dcf2302345570b4f738b28700266f87

After you have checkout the commit you want, you can then out the branch into the new branch you want with the following command:

sudo git checkout -b branch2

Moving on to file C, this one might be tricky but you can try:

  1. Switch back to master: sudo git checkout master
  2. Checkout a new branch of master for safety such as: sudo git checkout master-2
  3. Merge in branch1 into master-2. While on master-2 run: sudo git merge branch1
  4. Resolve the conflicts in any files listed if any. Do not skip any of them. then add and commit that branch, not push.
  5. Now, master-2 will have all the changes made on it. If you want you can merge this into master but you mentioned that file B needs to be an older file so I don't think a merge to master is ready.
  6. You will need to checkout branch1: sudo git checkout branch1
  7. Find the previous commit with the correct file B using sudo git log
  8. Use git revert to checkout the older commits as mentioned above. Once you find the once you want, check that out to a new branch using: sudo git checkout branch-fileb
  9. Touch (add an extra line, as touch might not register with git) the file B on the newly created branch. Add and commit the change/touch.
  10. Still on branch branch-fileb, merge back in branch1 using sudo git merge branch1
  11. Resolve the conflicts, and you should have the correct A, B, and C files you want.
  12. Merge master to prepare while on branch branch-fileb using: sudo git merge master
  13. Resolve all conflicts.
  14. Switch back to branch master, then merge in branch branch-fileb using: sudo git merge branch-fileb

And the branches should all be how you want them now.

For good housekeeping delete and local unused branched and any unused remote branches.

Upvotes: 0

VonC
VonC

Reputation: 1323863

A simple solution is, from where you are on branch1:

  • create branch2 (git checkout -b branch2), and remove C. Add, commit, and push
  • get back to master (git checkout master), and copy C from branch1 (git show branch1:path/to/C >path/to/C). Add, commit and push.
  • finally, get back on branch1, remove the extra files, add, commit and push.

That way, no merge, no history rewrite, not even a revert, just some additional commits pushed to remote to cleanup the current situation.

Upvotes: 3

Related Questions