Table of Contents
- Related Readings
- Common Tasks
- Manual Rollback
alias gitdiffcommit='git --no-pager diff HEAD' alias gitdiffprod='git --no-pager diff origin/master' alias gitdiffstage='git --no-pager diff' alias gitfilediffcommit='git diff --name-only HEAD' alias gitfilediffprod='git diff --name-only origin/master' alias gitfilediffstage='git diff --name-only' alias gitglog='git log --graph --decorate --all' alias gitlistallbranch='git branch -a' alias gitlistbranch='git branch -vv' alias gs='git status'
The objective is to transform the commit tree from left to right.
1. checkout testing branch
We first need to checkout the testing branch using command
git checkout testing.
2. Rebase testing branch on top of mainline branch
We could achieve this using command
git rebase mainline testing. This gives us the following structure:
Note: The instruction provided by
git rebase commands is useful but confusing. In case of conflict, we need to:
- Resove the conflict.
git addto mark the conflicts as resolved.
- Continue the rebase using
git rebase --continue. Now, there are two possibilities:
- We can move to next step. (Git will ask us to resolve new conficts. It's possible that we need to resolve different conflicts for the same files.)
- Git complains and asks us to check if we forget to execute
git add. Now we need to
git statusand see if there are unresolved conflicts. If we do have unresolved conflicts, go back to step 1.
- (Optional) Execute
git rebase --continueagain. (We will probably get the same complain.)
- Skip the current round using
git rebase --skip
Repeat the process until all conflicts are resolved.
3. Rebase mainline branch on top of testing branch
This can be done by executing
git rebase testing mainline command.
The objective of this step is to move the pointer of mainline branch to the last commit of the testing branch. After this step, we have
- pointer of mainline branch
- pointer of testing branch
all points to the last commit in the local environment.
4. Squash commits if needed
Note that we should be in the mainline branch now. With our example, if we execute
git status at this point, git should report we are currently 3 commits ahead of the origin/mainline.
If we want to squash commits in the testing branch, we could use command
git rebase -i HEAD~3, which produces the following result:
5. Check the local commit history before push
Perform sanity checks using
git log --graph --decorate --all!
By manual rollback, we mean to pick a old commit and commit to a new revision. Suppose we have the following git logs:
commit-X <-- latest commit, HEAD ... commit-G <-- The commit we want to rollback to ...
The objective is to have
commit-Y commit-X ... commit-G ...
commit-Y is exactly the same as the
To achieve this, we can
git reset --hard commit-G git reset --soft commit-X git commit -m "Manually rollback to commit-G."
For more details about
git reset, please refer to Git - Reset Dymystified.
Git has many "spaces":
- working space: This is basically the local directory that contains the code.
- staging space (Index): This is the space that stores the commited changes/files.
- head: Still not quite clear about this. It seems to be a pointer. It's ususally associated with a branch but a head can be detached from the branch.
The first command
git rest --hard commit-G will make all spaces (e.g. working space, staging space and head) have the exact files from
commit-G. This is the state when we push the changes from
commit-G. The hard reset basically allows us to go back in time.
The second command
git rest --soft commit-X will move the HEAD ponter back to the latest commit without changing the working space and the staging space. That's why after executing this command, git will detect difference compared to the latest commit (e.g. commit-X). At this point, we essentially copied all the files from commit-X to the local directory and we can use
git commit to create a new commit.
It's always a good idea to verify our work. Because we want to rollback to the
commit-G, after executing the commands, we can quickly verify the result:
git diff commit-G
The above comment should not produce any output because there should not be any difference compared to
----- END -----
©2019 - 2022 all rights reserved