Daily Git Dose! 💊

Bhavya Tyagi
8 min readJan 8, 2023

--

Are you moving to that new internship or going as a new hire? This blog is about day-to-day scenarios one may face at the job. It is for beginners and professionals who understand the basic functioning of Git and will help improve version control and keep things fresh.

Scene 1: Someone has pushed code to the remote repository, you don’t have that change, and you have also worked on the same code. You want to get that change and push your code as well.

Solution: An error is thrown because your local repository is not updated with the remote changes, and you are trying to change an older code version.

Error message due to unpulled remote changes

The first thing you need to do is try this command:

~% git pull origin master --rebase

In the case of mutual exclusive work, this command holds your changes momentarily and tries to update your local repository with the remote repository. If successful, it will write your changes on top of everything, and boom, you're sorted.

For example, if the remote change is mutually exclusive

Ensure your changes are committed before pulling anything from the remote repository.

But life is more challenging than it seems if you both have worked on the same part of the code. If the remote changes include any change where you have worked, merge conflicts may arise. In this scenario, you want to decide which version or part of the code to keep. After this selection, mark the conflicts as resolved, continue the rebasing process, and finally, push your changes to the remote repository.

~% git add .                    # marks conflicts resolved
~% git rebase --continue
:wq # edit rebase/latest commit message, write & quit.
~% git log # ensure if everything is well
~% git push origin master # final push to remote repository
For an example of the above comments, the same section of conflicts

Scene 2: You were working in a different branch, that branch has all the code you changed, but you want that change in the master branch so that you can push it.

Solution: It looks like you're done with another feature branch. Nice! But, oops! Other developers have already updated the remote repository with their new features.

For this scenario, the first thing is to ensure all your changes are safely committed in your feature branch. Then go to the remote/master branch and perform.

~% git pull origin master --rebase

Yeah, we've seen this command earlier, and we need to know that our local master branch is updated with the remote master branch. Now we merge our feature branch to the master branch. Go to the feature branch and perform.

~% git merge master
:wq # write a merge message, write & quit.

Now you may go back to your master branch and perform.

~% git merge featureBranch      # this should fast forward as 
# the branches are already merged
~% git push origin master # final push
  • This is how it looks after a successful merge with the master branch.
git log: feature branch merged with master

Important things to note!

  1. You may notice that we merged our branch to the master and did not play with the master branch first. This is not necessary. You may directly merge the master branch to your feature branch once you're in practice and no longer want to use the feature branch anymore.
  2. Like in the previous Scene, merge conflicts may arise if a section of interest is the same and several developers are working on a similar or related feature. Hence resolve the conflicts as discussed in Scene 1 and merge after the resolution. Some commands that may help are:
~% git add .                    # marks conflicts resolved
~% git merge --continue
:wq # write a merge message, write & quit.
~% git log # ensure if everything is well
Example for case 2
  • You can also rebase your feature branch with the master branch once you have pulled all the remote changes. This avoids the creation of an extra merge commit message and keeps the history clean. The commands are (Ensure master is updated with remote and you've your changes committed in the feature branch)
// In feature branch
~% git rebase master # rebase with master branch
~% git add . # marks conflicts resolved
~% git rebase --continue
:wq # edit rebase/latest commit message, write & quit.
~% git log # ensure if everything is well

// In master branch
~% git checkout master
~% git merge featureBranch # this should fast forward as
# the branches are already rebased
Final output in actual implementation
  • You can now push your new feature to the remote repository with a clean history of commits and no redundancy.

Scene 3: Diffs and Patches!

Diffs and patches make life easier in a wide range of applications. You can take diff between two commits or branches with Git and create a patch of commit(s) that can be applied to the same or different branch.

~% git format-patch -5 HEAD             # creates patch for last 5 commits
~% git apply 001-patch # apply the patch
~% git apply 002-patch # apply the patch
...

This, however, creates separate patch files for each of those commits, with formatted code changes that Git can understand and form commit with later on. Now you can cherry-pick the commits that are needed to be patched.

Another way is to take a diff of the last five commits and save it in a single file. This will help you navigate the changes of the last five commits in a single file and apply them in any branch as a single commit.

~% git diff HEAD~5..HEAD > patch.patch     # creates patch for last 5 commits
~% git apply patch.patch # applies patch
~% git commit -am "a single commit" # commit changes as a single commit

Scene 4: I am working across a lot of commits and working on multiple features simultaneously. How do I edit a specific commit or feature and keep things organized?

I found this very interesting when I saw this for the first time. To demonstrate that, I have kept five different files, one for each commit for my last five. The following screenshot will clear the setup a lot.

Scene 4 setup for demonstration

Suppose these are five features you are working on, and now you want to work on or modify the third feature. How can you make the changes to the third feature without adding any extra commit and maintaining the order?

Follow the steps:

  • Type the command:
~% git rebase -i HEAD~5          # last 5 commit, latest at bottom
git rebase -i: before re-ordering

Reorder these commits, and move the feature/commit with which you want to work at the bottom. For us, let’s take feature 3. Tip: press dd to delete a line, y to copy, and p to paste in the command mode of the editor.

git rebase -i: after re-ordering

Write & quit using :wq. Now, you may see in the git log that your commit has come up at the top, and as we have discussed in Scene 6, we can amend our changes to this commit without an additional commit.

git log: after re-ordering

Once you have made all your changes, you can either create a new commit or, to keep things limited to a single commit, use the command:

~% git commit -a --amend       # -a stages file that are modified 
# or deleted except the new ones
# here you may edit the last commit message

Once that is done, edit the commit message, if required, and write & quit using :wq. Re-order the commits in git rebase -i as shown above to come to the very beginning of the setup again, if required.

Hence you were able to edit a specific feature or commit and still keep things organized for you :). This helps when you’re developing several things and getting them reviewed. Once finalized, you can release those commits to the remote repository in a phased manner or gradually.

Scene 5: You corrupted a branch / too many merge conflicts.

This is where you might be scratching your head when the commands are not acting as they should, or you do not see all of the commits with the git rebase -i, or the incoming conflicts are Git of control. If you think the branch you are on is acting funny, it may sometimes be because of git configurations though, but whatever the reason, this is how you can retrieve your changes fresh and keep them safe.

Save all your changes in a patch till you have a safe commit. A safe commit, maybe until the remote is updated with your code or at a point where you feel the branch is taking commands properly. Save that commit hash, and all the changes/diff/commits above this hash can be saved as a patch.

Once a patch is generated(refer to Scene 3 for diffs and patches), you can hard reset to that saved hash of the safe commit. You can also create a new branch or work on the same. Once that is done, apply your patches or all changes as a single diff patch or as per need to keep things fresh and customized. Some of the commands that you may find helpful:

~% git reset --hard <hash>             # where hash is the earlier saved hash
# changes above this hash are deleted
~% git apply patch # applies all the commits
~% git reset --soft <hash> # this resets to the hash and keeps
# changes as staged

Scene 6: A significant feature has been added, but oops! Some tweaks are yet to be done, and I don’t want a separate commit.

This happens quite a time when we are working and trying to keep the commit history clean. A widespread solution is to use the --amend with git commit command. Let’s take a look.

~% git commit -a --amend       # -a stages file that are modified 
# or deleted except the new ones
# here you may edit the last commit message
:wq # write & quit

It is important to note if you have any files which Git do not know about, you must first add them using git add.

This blog contains a few of my experiences and learnings with Git. There might be better solutions in the future as things move fast. Please share your suggestions or thoughts, if any, or any scenes you may have encountered in your job. If you think something is incorrect, please let me know. I’d love to correct it. Refer to the Git Documentation for more :).

--

--

No responses yet