31d1afd5 HEAD@{0}: rebase finished: returning to refs/heads/feature 31d1afd5 HEAD@{1}: rebase: [commit message] | | A 73595077 HEAD@{27}: rebase: [commit message] | 24066915 HEAD@{28}: rebase: checkout master 70bef9e4 HEAD@{29}: checkout: moving from master to feature C 24066915 HEAD@{30}: rebase finished: returning to refs/heads/master 24066915 HEAD@{31}: pull upstream master: checkout 2406691540f36c1ca45fb3c7881ca9ca4b679465 45e96175 HEAD@{32}: checkout: moving from feature to master 70bef9e4 HEAD@{33}: rebase -i (finish): returning to refs/heads/feature C 70bef9e4 HEAD@{34}: rebase -i (pick): [commit message] | | Bwith :
HEAD is now at 70bef9e4 [commit message]And that's it !
It is a safe practice to experiment commands / anything you're not completely sure of on a copy of your data instead of the actual data. To do so, I usually git clone my repository into a temporary place then play until I understand how things work and I feel confident to apply changes to the real data.
But since a cloned repository has an empty reflog, git clone is helpless here.
As a workaround, it is possible to run :
What would happen if ... ?without actually trying it. However, it is pretty safe to try it :
A---B master \ C---D featureWe want the feature branch to be up-to-date with master.
command | merge | rebase |
---|---|---|
result |
A---B master \ C-B-D-E feature |
A---B master \ C'-D' feature |
pros |
|
|
cons |
|
|
merge vs rebasequestion is mostly context-dependent
---o---o---o master
---o---o---o---o---o---o master \ o---o---o feature
---o---o---o---o---o---o master feature_squash \ o---o---o feature
merge squashmy feature branch into the
squashbranch :
Squash commit -- not updating HEAD Automatic merge went well; stopped before committing as requested
---o---o---o---o--o---o master \ \ \ o feature_squash \ / o--o---o feature
squashbranch into master :
---o---o---o---o--o---o---o master feature_squash \ \ / \ o \ / o--o---o feature
squashbranch :
---o---o---o---o--o---o---o master \ \ / \ o \ / o--o---o feature
The title of this article as well as the solution below refer to master because it's a pretty common situation, but you can —of course— apply this to any branch .
cat << 'EOF' > .git/hooks/pre-commit #!/usr/bin/env bash currentBranch="$(git rev-parse --abbrev-ref HEAD)" if [ "$currentBranch" == 'master' ]; then echo 'None shall pass!' exit 1 fi EOF chmod +x .git/hooks/pre-commit
#!/usr/bin/env bash
currentBranch="$(git rev-parse --abbrev-ref HEAD)"
if [ "$currentBranch" == 'master' -a "$c2m" != 'yes' ]; then
echo 'None shall pass!'
exit 1
fi
F-------G myBranch / A---B---C---D---E master
F-------G myBranch / \ A---B---C---D---E---H master
A---B---C---D---E---H master myBranch
Branch branch set up to track remote branch branch from remote. Switched to a new branch 'branch'This :
fatal: Cannot update paths and switch to branch 'branch' at the same time. Did you intend to checkout 'myLocalBranch' which can not be resolved as commit?
Branch localBranch set up to track remote branch branch from remote.
Branch currentLocalBranch set up to track remote branch branch from remote.
This typically happens when you've committed on master, then realized that those commits better suit a feature branch. In other words, how may I go from this :
A---B---C---D---E master
to this :
C---D---E newBranch / A---B master
Before going further, make sure you have no uncommitted changes left.
git branch newBranch # Create a new branch, saving the desired commits git reset --hard HEAD~3 # Move master back by 3 commits (GONE from master) git checkout newBranch # Go to the new branch that still has the desired commits NB : instead of resetting to a nb of commits, you can reset until a specific commit ID : git reset --hard a1b2c3d4
You want to go back to C, and move D and E to the new branch. Here's what it looks like at first: A-B-C-D-E (HEAD) ↑ master After git branch newBranch: newBranch ↓ A-B-C-D-E (HEAD) ↑ master After git reset --hard HEAD~2: newBranch ↓ A-B-C-D-E (HEAD) ↑ master Since a branch is just a pointer, master pointed to the last commit. When you made newBranch, you simply made a new pointer to the last commit. Then using git reset you moved the master pointer back two commits. But since you didn't move newBranch, it still points to the commit it originally did.
NB : if you checkout newBranch from the existing master branch it ALREADY has those three commits included in it, so there's no use in picking them. At the end of the day to get what the OP wanted, you'll still have to do some form of reset --hard HEAD. https://stackoverflow.com/questions/1628563/move-the-most-recent-commits-to-a-new-branch-with-git#comment-36690393 Step 1 - Note which commits from master you want on a new branch : git checkout master git log Note the hashes of (say 3) commits you want on newBranch. Here I shall use: C commit: 9aa1233 D commit: 453ac3d E commit: 612ecb3 Note: You can use the first seven characters or the whole commit hash Step 2 - Put them on the new branch git checkout newBranch git cherry-pick 612ecb3 git cherry-pick 453ac3d git cherry-pick 9aa1233 NB : the order is important. You want to do the oldest commits first