- Need to master these concepts as they will be part of daily Git usage.
Become a well-informed developer by mastering essentials first and then going deep into each topic.
Each commit get a uniqie hash.
Each commit references atleast one parent commit. Only First commit i.e the initial one doesn't have a parent commit.
We are always working on a branch in Git. On running
git status
, we get the o/p as:
On branch master
nothing to commit, working tree clean
- Default branch name in Git is
master
whereas default branch name in Github ismain
. Just like a normal branch, nothing novel about it. - Although people put main copy of the project on it, but its not mandatory to do so.
Branches:
- Alternative timeline for project.
- Enable us to create separate context to try new features or even work on mutiple ideas in parallel. Ex. new-feature, color-scheme, layout-change, bug-fix etc. al happening on separate branches in their respective context.
- If changes are made on one branch, they don't impact the other branch unless changes are merged via combining branches.
- To build a new feature, create an experimental-branch from master branch. If the feature was approved, then merge the branch with the main branch else ignore the feature.
Understanding (HEAD -> master):
- HEAD: pointer that refers to current 'location' in your repo. It points to a particular
branch reference i.e name of the branch
. - branch pointer is where the bookmark is.
- HEAD: As of now HEAD points to the latest commit made on master branch. But gradually we will see that we can move it around.
- Branches are like bookmark in a book. At one point of time, only on given bookmark can be accessed/opened/viewed/active. That is what HEAD refers to, the current location we are viewing or checking out.
- Last commit made was the tip of the master branch. HEAD refers to this branch pointer.
- If we switch the different branch, HEAD points to tip of that branch.
- Branch pointer(i.e branch-name Ex. master) keeps moving as we keep making new commits pointing to new commit-hash. Whereas HEAD pointer still points to branch-pointer i.e. master.
- Ex. To switch to a branch say dark-mode, HEAD should point to new branch-pointer i.e dark-mode. Now new commits will be made to this dark-mode branch. Master pointer won't move & will stay where it was earlier.
- Whenever we want, we can switch back to the old state, we move the HEAD back to that branch-pointer.
- We can have 100s of branches and each branch has a branch-reference(or name of branch) which is pointing to where we left off that branch.
- A branch is just a reference to some commit. As we make new changes, the branch-name which is branch-pointer updates to point to a new commit.
View all existing branches in a repo:
git branch
- Currently active branch i.e on which we are right now will have an asterisk on it.
Creating Branches:
git branch <branch-name> : Make a new branch based upon current HEAD
- It only creates the branch, doesn't switch the HEAD to the newly created branch. HEAD still remains the same.
- Two branches will be referring to same parent-commit if they were created from that commit.
git branch color-scheme
git log: HEAD-> master, color-scheme
Switching Branches: [NEWER WAY using switch]
git switch <branch-name>
- After the newly branch is created, use the above command to switch to the branch.
- Its the HEAD which switches to newly created branch.
git switch color-scheme
git log: HEAD->color-scheme, master
- If a new commit is made on this branch, then master will be left behind and HEAD will move on with the tip of this color-scheme branch.
git log: (HEAD -> color-scheme)
commit 3829472394... (master)
- The location we are on, makes a huge difference when we branch out.
- Both branches will refer to the same commit from where they were created.
Older Way to switch using checkout
- git checkout
-
checkout
does a lot of other things than just switching branches, hence it was decided to bring a standaloneswitch
command to the table.
- Both achieve the desire result i.e checkout & switch.
Single step branch creation & switching:
-c : create flag
git switch -c [NEWER way]
git checkout -b [OLDER way]
Switching branches with unstaged/ uncommitted changes:
- Changes made to file, but not staged or committed.
- If we try to switch in such a state of uncommitted changes, then the changes made will be lost i.e overwritten by checkout.
- Hence, either commit the changes or stash them before switching a branch.
- A newly created file which is a single copy on this branch, hence not in any conflict with any other branches. Then in that case, even if its unstaged/uncommited, it will follow you even after you have switched the branch also. Hence, always add & commit changes before switching branches.
Deleting a branch:
git branch -d
git branch --delete
- The branch must be fully merged in its upstream branch, or in HEAD if no upstream was set to --track or --set-upstream-to
- Possible Error1: You can't delete the branch you're on. Hence, switch to another branch before deleting the branch.
- Possible Error2: It should be fully merged,
- Force deletion via -D deletes the branch irrespective of the merge status.
-
-D
flag is short for --delete --force -
-M
is short for --move --force -
-C
is short for --copy --force
Rename a branch:
- Switch to the branch which needs to be renamed.
git branch -m <new-name-for-this-branch>
Knowing more about HEAD:
- Inside .git directory, HEAD references a branch and each branch references a commit i.e
HEAD --(references)--> branch reference --(references)--> commit
- ls -a
- cd .git
- ls
- cat HEAD : shows ref: refs/heads/master i.e HEAD is pointing to master
- If branch is switched, and we execute the above set of commands, then HEAD will point to different branch reference[i.e branch name] .......
- cat HEAD : shows ref: refs/heads/color-scheme i.e HEAD is pointing to color-scheme
- refs/heads/master, refs/heads/color-scheme etc. actually reference a particular commit.
- There will be a file for every branch inside refs/heads directory. And in each of these file, there will be just one thing which is commit-hash
- Hence, branch-reference[or branch-name] is a pointer to a particular commit.
- So, HEAD was refs/heads/master. And refs/heads/master is actually a commit-hash. Thats where the bookmark for the branch is left off.
- HEAD = is currently we are checked-out on.
- HEAD points to one of those branch-references. And branch-references point to one of those commit-hash.
- We switch HEAD from one location to another.
Merging:
- One of the most critical aspect. Following topics to be mastered very well as they will be part of daily workflow.
- Fast-forward Merge,
- Git Merge & Merge commits
- Merge conflicts
Merging:
- Branching gives us an isolated context to work upon a feature, and when we are done with the it then we need to incorporate those changes into the main branch. This is done using
git merge
- If a feature didn't worked out as expected, branch is abandoned.
- Merge back the feature branch into the master branch if feature worked out as expected.
- Branches are defined by a branch-pointer.
- Remember: Branches are merged, not specific commits. Also, we always merge to the current HEAD of the branch i.e where HEAD is now.
Fast-forward Merge Process:
[Main branch has no new commits, feature branch can be directly merged in it.]
1. Switch or checkout to receiving branch in which we need to merge.
`git switch main`
2. Use `git merge` to merge changes from a specific branch into current branch.
`git merge feature`
git branch -v : branch name abbr-hash tip of branch with last commit
Official Docs for further reading:
https://git-scm.com/docs/git-branch
https://git-scm.com/docs/git-switch
https://git-scm.com/docs/git-checkout