git advanced

HEAD and detached HEAD

  • when you checkout to a branch, git is pointing to the latest commit in that branch, which is the HEAD of that branch

Detached HEAD

  • you can also checkout to a specific commit in any branch, when you do that, that commit becomes a detached HEAD, it doesn’t belong to any branch anymore.
  • if you made some changes in the detached HEAD and commit it, it is better to create a new branch (which contains all the changes you made), before switching back to other branches, then you could merge the new branch into the master branch. Otherwise if you don’t create a new branch, the changes you made in detached mode will be lost.

Undo changes

git restore

  • you could use git restore <file-name> or git restore . to revert all unstaged changes

git clean

  • you could use git clean -d to delete new files (unstaged)

Undo staged changes

  • git restore --staged <file-name>
  • this will copy the latest commited file to the staging area, which basically means it will revert all changes that currently are in the staging area now

Deleting commits

soft

  • git reset --soft HEAD~1
  • commit will be deleted, changes will still be in the staging area

mixed (default)

  • git reset HEAD~1
  • commit will be deleted, changes will be removed from the staging area, but the changes will still be in the working directory

hard

  • git reset --hard HEAD~1
  • commit will be deleted, all changes will be removed from the staging area, the all changes will be removed from the working directory too

Stash

add current changes to Stash with a comment

  • git stash push -m "message"

see the list of stashed changes

  • git stash list

add changes back to unstaged state and remove from Stash

  • git stash pop <index>

add changes back to unstaged state but also keep it at Stash

  • git stash apply <index>

remove a particular stash from the list

  • git stash drop <index>

clear the entire stash list

  • git stash clear

Reflog

  • allows us to bring back lost information, it could be commits or branches
  • use git reflog you will see a list of commits for the last 30 days, even the commits you deleted, which can’t be found in git log. Then you could use git reset --hard <commit hash code> to retrieve lost commits

Merge

fast forward

  • can only be used when no additional commit in master (after feature branch was created)
  • MERGE moves HEAD forward to the latest commit but does not create new commit

fast forward with squash

  • git merge --squash <branch name>
  • all commits you made in the feature branch will be combined into one new commit when you MERGE it to the master branch
  • more specifically, when you use --squash, all the changes you made across all commits will be move to the staging area in the master branch.

recursive

  • additional commits in both master and feature branch after feature branch was created
  • additional commit is created in master branch when MERGE
  • NOTE: when you use recursive MERGE, all commits either originated from the feature branch or the master branch, will be showing in the log history. But to revert the commit, you only need to revert for 1 step: git reset --hard HEAD~1
  • if you don’t want to see the commits from the feature branch to be display in your master git log history, you could use --squash with recursive MERGE

rebase

  • when you have new commits for both master branch and feature branch (after you created the feature branch), you could use rebase to let the latest commit in master branch becomes the new base commit for commits created in feature branch
  • after rebase in the feature branch, all commits you made in the feature branch will have new commit code, even though the changes for these commits are the same. These might raise issues when working with others outside the repo because you will have different commit history

when to use rebase?

  • you could use rebase when there is new commits in the master branch

why use rebase?

  1. feature branch relies on additional commits in the master branch, then you could rebase the master into feature branch
  2. feature branch is finished, you want to merge it into master without creating new merge commit
  • you could first rebase master into feature branch
  • then you could use fast-forward merge because now your master branch don’t have any new commits to your feature branch (because you rebased)

cherry-pick

  • add a specific commit from feature branch to your master branch
  • a new commit ID will be created, even though the commit content is the same
  • useful when you want just a commit to be in your master branch, but you don’t want to merge the entire feature branch

Github

deleteing commits in github

  • we could use git reset --hard HEAD~1 to delete local commits
  • but when we use git push to push to remote git repo, it will fail because our local branch is behind the remote branch
  • we could use git push --force origin master to force push changes to remote repo, in this case the remote commits will be deleted.