Open dorawyy opened 7 years ago
git revert
conflict scenario TestIn the testcase above
rollback1
and rollback2
branches both have commits, no conflict;
Previous project status:
Committed on both rollback1
and rollback2
:
# rollback1 : test12-revert1
git checkout rollback1
touch test12-revert1
vim test12-revert1
git add test12-revert1
git commit -m "rollback1: created file test12-revert1"
# rollback2: test12-revert2
git checkout rollback2
touch test12-revert2
vim test12-revert2
git add test12-revert2
git commit -m "rollback2: created file test12-revert2"
Project status becomes (diverge with no conflict):
git checkout rollback1
git merge rollback2
An auto-merge commit is created:
The project status becomes:
rollback2
forward, then make another commit after merging# merge rollback2 forward
git checkout rollback2
git merge rollback1
# make a new commit
git checkout rollback1
touch test12-revert-common
git add test12-revert-common
git commit -m "rollback1: create file test12-revert-common after merging"
# sync the two branches
git checkout rollback2
git merge rollback1
rollback1
from head
to head^^2
(suppose no conflict)(suppose a revert commit is created, however, no conflict during revert)
git checkout rollback1
git show --oneline head ##456a9fa (current head)
git show --oneline head^^2 ## 22ae3cb (on rollback2)
git revert head^^2
An auto-commit window pop up, asking the developer to fill in revert commit message
When the revert is done, the project history becomes:
sync branch rollback1
and rollback2
by resetting rollback1
to head^
git checkout rollback1
git reset --hard head~
Project status becomes:
both commits on rollback1
and rollback2
, conflict when merging, take the version of rollback1
when resolving the conflict
rollback1
and rollback2
# commit on rollback1 branch
git checkout rollback1
vim test12-revert-common
# edit line1
git add test12-revert-common
git commit -m "rollback1: edit line 1 of file test12-revert-common"
(edit on rollback1
)
project status becomes:
# commit on rollback2 branch
git checkout rollback2
vim test12-revert-common
# edit line1 (same as rollback1)
git add test12-revert-common
git commit -m "rollback2: edit line 1 of file test12-revert-common"
(edit on rollback2
)
Now the two branches diverge, with conflicts:
rollback1
, merge rollback2
(with rollback1
version file)git checkout rollback1
git merge rollback2
Conflict here, need to be resolved. The conflict file test12-revert-common
now is:
After resolution:
then merge again:
git add test12-revert-common
git commit -m "resolve merge commit with rollback1 version"
The project status becomes:
git checkout rollback1
touch test12-revert-after-merge
git add test12-revert-after-merge
git commit -m "rollback1: commit after merge"
# sync the two branches
git checkout rollback2
git merge rollback1
rollback1
, revert from head
to head^^
(rollback1
version), same as merge versiongit checkout rollback1
git show --oneline head ### 3f20762, current head
git show --oneline head^^ ### 593f5de, commit on rollback1 (same as the merge version)
# revert
git revert head^^
An auto-merge commit is issued, no revert conflict:
Then, project status becomes:
git checkout rollback1
git reset --hard head~
rollback2
branch version when merging, then reverting to head^^
agingit checkout rollback2
vim test12-revert-common
# edit line1 (same as rollback1)
git add test12-revert-common
git commit -m "rollback2: edit line 1 of file test12-revert-common"
(the edit on rollback2
is:)
git checkout rollback1
git merge rollback2
# fix with rollback2 version
git add test12-revert-common
git commit -m "resolve merge conflict: fix with rollback2 version"
(resolve merge conflict with rollback2
version)
after merging, the project status become:
Create another commit after merging
git checkout rollback1
touch test12-revert-after-merge
git add test12-revert-after-merge
git commit -m "rollback1: commit after merge"
# sync the two branches
git checkout rollback2
git merge rollback1
The project status becomes:
rollback1
, reverting to head^^
( same version as rollback2
, different from )git checkout rollback1
git show --oneline head ### 07e4598
git show --oneline head^^ ### 593f5de (rollback1 commit)
# revert
git revert head^^
## revert conflict
(revert conflict arise)
(current git status
)
(content of the conflicting file -- test12-revert-common
)
If we change the file when resolving conflicts to:
Then, then continue revert
git add test12-revert-common
git revert --continue
A revert commit is created:
now the project status becomes:
This is tested by replaying the Test2
above of git revert
rollback1
, revert
to head^^2
(134cc79
)The conflict file version is now:
revert
version of the file after resolving conflict:
Then, continue the reverting:
When issuing the command git revert --continue
, a revert commit will be created, and ask developers to input message to attach (see next step)
a revert commit will be created, developers can input conflict-resolving information (here is the default info)
now the revert conflict is resolved, the project status becomes:
reset the revert process, make project history clean again
git checkout rollback1
git reset --hard head~
The project status becomes:
experimenting with file test12-revert1
. The start state of the file is:
project status:
file list on rollback1
:
git checkout rollback1
vim test12-revert1
git add test12-revert1
git commit -m "rollback1: 'x=commit1' in file test12-revert1"
(edit in the file test12-revert1
is highlight with blue: )
After commit1, project status becomes:
After commit1, file list becomes: (no change)
git checkout rollback1
vim test12-revert1
git add test12-revert1
git commit -m "rollback1: 'x=commit2' in file test12-revert1"
(edit in the file test12-revert1
is highlight with blue: )
After commit2, project status becomes:
After commit2, file list becomes: (no change)
git checkout rollback1
vim test12-revert1
git add test12-revert1
git commit -m "rollback1: 'x=commit3' in file test12-revert1"
(edit in the file test12-revert1
is highlight with blue: )
After commit3, project status becomes:
After commit3, file list becomes: (no change)
git revert head^^
( at commit3
, revert commit1
)git checkout rollback1
git show --oneline head ## 2bb579d, commit3
git show --oneline head^^ ## 9cda35f, commit1
git revert head^^
Revert conflict arise in file test12-revert1
:
The file test12-revert1
becomes:
Then resolve the revert conflict by modifying test12-revert1
to :
Then. issue the command to continue revert:
git add test12-revert1
git revert --continue
The automatically-generated commit message is:
Revert conflict resolved by now, project status becomes:
git revert
Scenario scratchesAs long as the head
and the commit you want to revert, having different versions of the change part, there will be revert conflict;
For example:
0
-->1
is: x=0
--> x=1
, and the current state is x=1
head
is: x=3
1
on tip of head
, head
will try to make change x=1
--> x=0
, but found x=3
, conflict arisinggit revert
The revert just failed and got aborted, as no parent of the merge commit is specified, the revert does not know which parent commit to compare with
Specifying -m
, which stands for mainline-parent-commit to use when reverting
-m
specified#revert to the first parent of the merge commit, which is commit2 in this case;
git revert head^ -1
Revert conflict arise:
The whole file got compared here, though in both commits, the line z=1
are the same.
Based on the scenario of #11 , let's continue the test cases about rolling back, in this issue
Abstract:
As we know, here are several ways to rollback the project to a history version, which are:
git checkout
git reset
git revert
In this issue, we are comparing above ways of rolling back.
Scenario:
rollback1
androllback2
, and current state is:134cc79
, akahead^^2
.Results:
git log
are different in un-merged branchesIf trying to look into forward commits, git will return fatal info
YES, checked-out branch affects what commit the developer can rollback
git checkout
,git revert
,git reset
only affect current checked-out branch. They have no effect on other branches.git checkout
,git revert
,git reset
:git checkout
moves the pointer back to the specified commit, adetached head
state. If no reference to that commit created, new commits based on the specified commit (implemented in thedetached head
state) will get lost;git revert
creates a new commit to revert the specified commit, on the checked-out branch.revert conflict
might show up here, required the developer to resolve the conflict to continue reverting.git reset
removes the specified commit from the checked-out branch. Those commits are no longer visible ingit log
, however, the reset history is noted down ingit reflog
locally.Way1:
git checkout
Manual
Workflow
git checkout <commit>
to checkout to a detached HEAD state, which means simply thatHEAD
refers to a specific commit, as opposed to referring to a named branch.git checkout -b <new_branch>
- create a new branch, move HEAD there, no longer in detached stategit branch <new_branch>
- create a new branch, but leave the HEAD detachedgit tag <tag_name>
- leave the HEAD detachedQuestions to solve:
head
moves back to the commit we are checking outgit checkout <other_branches>
?head
be after creating references?head
does not change untilgit checkout
to other branch/commitsgit log
andgit reflog
change in the whole process?git checkout
won't affect other branches and done commits.Test1:
git checkout head^^2
, thengit branch <new_branch>
head^^2
It show currently, it is in the detached HEAD state
After creating the new branch, the state has not changed yet.
Now, it is no longer in the detached state.
Other branches are not affected at all.
The project history becomes ( with a new branch created, pointing to the commit
134cc79
:Test1 Summary: when
git checkout <commit>
, just movehead
pointer back. All commits in the repo as well as other branches are not affected.Way2:
git revert
Manual
git revert
-n
option, only reverting working tree and index back to the commit we would like to go back, no new commit created.Questions
git revert
affect other branches?HEAD
? Where isHEAD
before and after moving the commit?HEAD
moves a commit forward.git reflog
?git log
).git reflog
also gets changed. One finding aboutgit reflog
is that: it is always the same viewed from different branches.Test2
Meeting conflict when reverting back to
head^^2
(there was conflict when merging the two commits)The current version of
test11
is:Then resolve the conflict: ( if we use the file test11, current version, then)
The revert is done now.
Conclusion: other branches are not affected by reverting.
Fix current
git tree
, syncing branchesrollback1
androllback2
for next test.Way3:
git reset
Manual
git reset [<mode>] [<commit>]
<commit>
) and the working tree depending on<mode>
. If<mode>
is omitted, defaults to--mixed
. The<mode>
must be one of the following:--soft
: Does not touch the index file or the working tree at all (but resets the head to<commit>
, just like all modes do). This leaves all your changed files "Changes to be committed", as git status would put it.--mixed
: Resets the index but not the working tree (i.e., the changed files are preserved but not marked for commit) and reports what has not been updated. This is the default action.--hard
: Resets the index and working tree. Any changes to tracked files in the working tree since<commit>
are discarded.--merge
: Resets the index and updates the files in the working tree that are different between<commit>
andHEAD
, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added). If a file that is different between<commit>
and the index has unstaged changes, reset is aborted.--keep
: Resets index entries and updates files in the working tree that are different between<commit>
andHEAD
. If a file that is different between<commit>
andHEAD
has local changes, reset is aborted.Test3
Current project history is:
If we checkout
rollback1
, reset the commit we did in test2:The revert is done. Now let's check the change in log and
head
pointerThe
head
pointer moved 1 commit back, same asrollback2
branch now.Working tree and index empty.
When
--hard
resetting, the previous latest commit got removed directly fromgit log
However, the reset can be tracked via
git reflog
Also, checking status of other branches
Summary:
git reset
does not affect other branches, only reset current checked-out branchgit reset
removed the commit fromgit log
, however, the revert info is logged ingit reflog