Git Notes

 Imp points:

General points:

  • Rename a  branch -> First checkout to the branch which should be renamed  then use git branch -m <new name> 
  • git detached head mode, nice blog here
Git Fetch and Pull:
  • To see all remote branches, use gir branch -r
  • If a remote branch exists with name test,which can be viewed using git branch -r. If we want to create a local branch for the same use git switch branch name.
    This will do 2 actions:
    1. Create a local branch with name test
    2. Set up track top point to origin/test(which can be seen in .git/config  file) 
  • git fetch origin test3 or  git checkout test3  -> only fetches test3 branches info from remote to local but git fetch gets info of all branches in remote origin
  • when using git pull(above 2.27.0), we need to specify how to reconcile divergent branches, using opions discussed here else it wil promt the warning
  • Before pulling the changes if we want to see want has changed in master,  you can fetch the changes and go to remote/<branchname> (This is called detached head mode) and view all your changes.
    If you feel good just get those changes.
  • When we use git pull, the  changes of remote/<branch> are merged into local branch.So we don't need to specify origin <remote branch> but in case of fetch if we use git fetch, it will fetch info of all git remote branches.If  you want any specific branch specify git fetch origin <branch name>
Git log:(VVVImp)
  • when you perform 3 way recursive merge and see the log using git log then you shock because git  log shows history from other branch as well

    Instead use git log --first-parent or git log --graph(to see grapsh view)
    more detailed explanation: here
    or other solution is use --squash,which will  wait for squashing to happen,so it replaces all the commit messages with single commit msg,  which you should add immediately afterwards. 
    git merge --squash <branch name>
    git commit -m "commit msg"
  • Improve your git log command by setting alias as shown here

Git Diff:

  • git diff  -> without additional options, git diff lists all the changes in our working dir that are not staged for next  commit(Basically diff betwwen working dir and staged contents)
  • git diff HEAD -> lists all changes in the working tree since last commit.(Even changes which we are staged)
Git stash:
  • Git stash basic commands here
  • When you work on a branch and meanwhile you wanted to switch to another branch and before switching if you don't stash or commit changes then changes will commit to other branches(which is no good) if there are no conflicts
  • Here conflict has a different meaning i.e if you want to switch to branch a from branch b, If you try to merge branch b into a then observe for coflict.(If fast forward mege is  possible then you don't get any conflicts)
  • If you get conflicts, git will intelligenly predict and it will promt error:  unable to switch else i.e if no errors then it will carry the changes
Question:

You demonstrated nicely these two scenarios:

1. changes come with us

2. conflict happens

But, when I think about it, I still see conflicts every single time. Let me explain.

You have master and purple branches. Branch master has empty CSS, purple doesn't. So when you switched (with uncommitted changes) back to master, there wasn't conflict. How? Wouldn't there be conflict because master says "I don't have styles", and purple says "I have styles"? So, how is that not considered by a conflict?


I hoped you understood my confusion :D

Answer:

It's a good question!  Suppose I have one branch "original" where I've made some commits and then I create a new branch from that original branch called "newFeature".  Then I start working on newFeature, where I create a new file called puppies.css and then create a new commit.  This commit and puppies.css only exists on the newFeature branch. The original branch does not have this commit, and it does not contain any additional new work.

If I then go to the original branch and try to merge in the changes from newFeature will we get a conflict or not?  The newFeature branch has the puppies.css file.  The original branch has no puppies.css file.  Is that a conflict?

The answer is no, we don't get a conflict!  "Disagreement" between branches is not what results in a conflict. In this case, Git can perform a fast forward merge because newFeature has all the same history as the original branch plus one new commit.  So Git can easily bring that new commit over to the original branch.   

On the other hand, if we also had new commits on the original branch that didn't exist on newFeature...then we would get a conflict.  Git "thinks" in terms of commits.  So if the original branch has commits that don't exist on newFeature, and newFeature has commits that don't exist on original...that's how we could get a conflict. 

Returning to your original question about switching branches: Wouldn't there be conflict because master says "I don't have styles", and purple says "I have styles"? So, how is that not considered by a conflict? There won't be a conflict unless we have work that was done on master that doesn't exist on purple AND we have work on purple that doesn't exist on master.   But that's not the case.  Instead, we just have some work on purple that doesn't exist on master.  So no conflict.  Does that make sense or am I just confusing you with this massive essay!?

Git Interactive rebase:
  • The commit messages will be seen in reverse, the git reads msgs  from the start and do all actions
  • If you reword a commit message(i.e fixing typo in commit message) then it will change commit hash from that particular commit to all the way to the top(Because each commit stores its parents commit details(refer git internals))
  • Difference between fixup and squash is  both are used to meld other commit messsage into previous commit message.squash will comment the one which you want to discard so that you can edit it in next step but fixup just altogether deletes it. Detailed explanation with number 5 here
  • drop will delete commit message and even changes made in that commit

    Git Undos:

    3 types:

    1. Undoing changes in working dir:
    • Either modifying files or creating files, before staging they will be in working dir, If we need to undo them then we have 2 options
    1. git checkout HEAD <filename> or git chekout -- <filename>(In older versions)
    2. git restore <filename>(In newer version)
      With git restore we can even change the content of file how it looks like a couple or more comis ago.cmd for the same: git restore --source HEAD~1 <filename>(or even commit id instead of HEAD~1)
    Note: Due to backward compatabilty checkout will be supported in new versions as well.

    2. Undoing changes in staging dir:

    Below is the simple command used to unstage staged file and it move it back to working dir(It doesn't change file contents)
    git restore --staged <file>

    3. Undoing commited chnages:

    This can be done using git reset, 2 types of resets
    1. mixed reset: Will undo the latest commit and changes will be moved to working dir
    2. hard reset: Will undo latest commit and even deletes file changes as part of the commit

    We can even undo more than one commit

    revert is another option, It will undo the commit and changes as well but creates another commit msg with the message of revetion, which will be used to backreference(It is mot widely used though)


    Git Merge:
    In Git, there are different types of merges that can be performed depending on the requirements and circumstances of the project. Here are some common types of Git merges:

    Fast-forward merge: A fast-forward merge occurs when the target branch has no new commits since the source branch diverged from it. In this case, Git simply moves the target branch pointer to the latest commit on the source branch, effectively incorporating all the changes from the source branch into the target branch. The commit history appears as a linear progression without a separate merge commit.

    Three-way merge: A three-way merge is the standard merge operation in Git. It occurs when the target branch and the source branch have diverged, and both branches have introduced new commits since their common ancestor (merge base). Git analyzes the changes made in each branch since the merge base and attempts to automatically combine them. If there are conflicting changes, it creates a merge commit and asks the user to resolve the conflicts manually.

    • It is very simple, if there are multiple conflicts while merging then it just stops with conflicts, we need to manually resolve them and we need to perform git add and git commit
    Git Rebase:

    When you perform a git rebase operation, Git replays commits from one branch onto another branch. It essentially modifies the commit history by creating new commits based on the original ones.

    To understand the internals of a Git rebase, let's consider the scenario where you have a feature branch and you want to rebase it onto the latest commit of the main branch. Here are the steps involved:
    1. Identify the common ancestor: Git identifies the common ancestor commit between the feature branch and the main branch. This common ancestor serves as the base for the rebase operation.
    1. Create a temporary copy: Git creates a temporary copy of the feature branch.

    2. Check out the main branch: Git checks out the main branch, moving the HEAD pointer to the latest commit on the main branch.

    3. Apply the commits: Git starts applying the commits from the temporary copy of the feature branch onto the main branch. It goes through each commit, one at a time, and applies the changes introduced by that commit to the main branch.

    4. Handle conflicts: If there are conflicting changes between the commits being replayed and the state of the main branch, Git pauses the rebase process and asks you to resolve the conflicts. You need to manually modify the code to incorporate the desired changes and then continue the rebase process.
    5. Complete the rebase: Once all the commits have been applied successfully or conflicts have been resolved, Git completes the rebase by moving the branch pointer of the feature branch to the last replayed commit. The original commits from the feature branch remain intact, but the commit history has been modified to incorporate the changes onto the main branch.

    By replaying the commits from one branch onto another, git rebase allows you to incorporate the changes from the feature branch onto the main branch in a more linear and cohesive manner. It helps in maintaining a cleaner commit history and can make it easier to understand the evolution of the codebase.

    However, it's important to note that modifying the commit history with rebase should be done with caution, especially when working in a collaborative environment where other developers may have based their work on the original commits.


    Rebasing replays changes from one line of work onto another in the order they were introduced, whereas merging takes the endpoints and merges them together.


      Do not rebase commits that exist outside your repository and that people may have based work on.


      You can get the best of both worlds: rebase local changes before pushing to clean up your work, but never rebase anything that you’ve pushed somewhere. 


        VVVIMP: While rebasing if your branch has many conflicts(i.e more commits which may cause conflicts) then you need to resolve conflicts so many times. This is time consuming and bestway to do this is first squash all the commits into a single one using git interactive rebase and then rebase now.

        Git rebase: video
        Git interactive rebase: video

        Comments

        Popular posts from this blog

        Helm Charts