Currently I am working on a 64-bit API for a storage server at work. The plan is to port a limited number of APIs in order to be able to call them directly from other applications / services without having to marshal such calls. I am trying to convert the data structures from 32 to 64 bits while keeping backwards compatibility. At some point in time we should be able to port with little additional effort the current storage server to 64-bits and still support client applications / servers running on 32-bits.
Following is a screen dump of a utility we use to count the lines of code (LOC). The results for this port at this time follow:
[30] >>> 30 >>> specify the path [c:\icas64\]: TreeCountSourceLines <<< count: 55 line: 12955 TreeCountSourceLines <<< path ==>c:\icas64\<== fileCount: 27 functionCount: 113 lineCount: 66987 line: 44157
A week or so ago I was chatting with a colleague regarding the advantages / disadvantages of using git merge versus git rebase. Most developers typically use git merge in order to merge a feature branch back into master. In case you are working on a private project, or with a reduced number of developers, probably you would prefer to use git rebase. The reason for this comes from the Git documentation which I will paraphrase here:
“The Perils of Rebasing
Ahh, but the bliss of rebasing isn’t without its drawbacks, which can be summed up in a single line:
Do not rebase commits that exist outside your repository and people may have based work on them!!!
If you follow that guideline, you’ll be fine.
If you don’t, people will hate you, and you’ll be scorned by friends and family.”
In order to go through an example, let’s use the following diagram:
The idea is to start with a master branch. We have a first commit labeled m1 followed by a second one labeled m2. At that point we create the feature branch. Once we are in the feature branch we make a commit for feature one labeled f1 and later we commit feature two labeled f2. In parallel the team makes a commit on the main branch labeled m3.
What we want to do now is consolidate the changes of the feature branch back into master. This is quite typical on most projects. The question is how to proceed. Do we use git merge of git rebase?
Let’s start by creating the scenario illustrated in the Git Merge vs. Git rebase diagram. Please keep in mind that there are many ways to get to a similar scenario. I will attempt to illustrate each step that we will use.
# **** create master branch with first commit (m1) **** C:\Users\John>cd c:\temp\gitplay c:\Temp\GitPlay>code . c:\Temp\GitPlay>dir 05/20/2019 11:31 AM 2 index.html <==== c:\Temp\GitPlay>type index.html m1 <==== c:\Temp\GitPlay>git init Initialized empty Git repository in c:/Temp/GitPlay/.git/ c:\Temp\GitPlay>git add index.html c:\Temp\GitPlay>git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: index.html c:\Temp\GitPlay>git commit -m "m1" [master (root-commit) 6ef1917] m1 1 file changed, 1 insertion(+) create mode 100644 index.html c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean c:\Temp\GitPlay>git log commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1
We will start by creating a folder and use Visual Studio Code (the IDE does not matter, we could have used any editor) to create a file named index.html (once again, the name does not matter). We will write in the file the name of the first commit (in this case m1). After initializing git, we add and commit our code to the master branch.
# **** modify and commit to master **** c:\Temp\GitPlay>type index.html m1 m2 <==== c:\Temp\GitPlay>git add index.html c:\Temp\GitPlay>git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html c:\Temp\GitPlay>git commit -m "m2" [master 0962747] m2 1 file changed, 1 insertion(+), 1 deletion(-) c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean
We add “m2” to the contents of the index.html file and commit it with the label “m2”. AT this point we have the top left two commits on master done.
# **** create feature branch, new file and commit f1 **** c:\Temp\GitPlay>git branch feature <==== c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean c:\Temp\GitPlay>git branch -a feature <==== * master c:\Temp\GitPlay>git checkout feature Switched to branch 'feature' c:\Temp\GitPlay>git status On branch feature nothing to commit, working tree clean c:\Temp\GitPlay>mkdir feature c:\Temp\GitPlay>cd feature c:\Temp\GitPlay>code . c:\Temp\GitPlay\feature>dir 05/20/2019 11:52 AM 4 index.html c:\Temp\GitPlay\feature>type index.html f1 c:\Temp\GitPlay\feature>git status On branch feature Untracked files: (use "git add <file>..." to include in what will be committed) ./ nothing added to commit but untracked files present (use "git add" to track) c:\Temp\GitPlay\feature>git add index.html c:\Temp\GitPlay\feature>git status On branch feature Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: index.html c:\Temp\GitPlay\feature>git commit -m "f1" [feature 24ded46] f1 1 file changed, 1 insertion(+) create mode 100644 feature/index.html
We now create a new branch which we label it as feature. In our workspace we create a folder name feature and in it we create a index.html file with our IDE. We just ass the string “f1” and commit it using the comment “f1”. The naming convention will help us follow that things are being done correctly and that the results are as expected.
On our diagram we now have the feature branch and a single commit labeled “f1”.
# **** switch to master to commit m3 **** c:\Temp\GitPlay\feature>git branch -a * feature master c:\Temp\GitPlay\feature>git checkout master Deletion of directory 'feature' failed. Should I try again? (y/n) n Switched to branch 'master' c:\Temp\GitPlay\feature>git status On branch master nothing to commit, working tree clean c:\Temp\GitPlay\feature>git branch -a feature * master c:\Temp\GitPlay\feature>git status On branch master nothing to commit, working tree clean c:\Temp\GitPlay\feature>git log commit 09627479545123f87ad603bfc6a0249d2b601b35 (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1 c:\Temp\GitPlay\feature>git checkout feature Switched to branch 'feature' c:\Temp\GitPlay\feature>git log commit 24ded46eaec4b8c5b467fb549028e5108cf6a19d (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:58:33 2019 -0500 f1 commit 09627479545123f87ad603bfc6a0249d2b601b35 (master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1 c:\Temp\GitPlay\feature>cd .. c:\Temp\GitPlay>git checkout master Switched to branch 'master' c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean c:\Temp\GitPlay>type index.html m1 m2 m3 c:\Temp\GitPlay>git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html no changes added to commit (use "git add" and/or "git commit -a") c:\Temp\GitPlay>git add index.html c:\Temp\GitPlay>git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html c:\Temp\GitPlay>git commit -m "m3" [master bbf5ed7] m3 1 file changed, 1 insertion(+), 1 deletion(-) c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean c:\Temp\GitPlay>git log commit bbf5ed72d70b43808f92baf80772064183d8dd60 (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 14:14:45 2019 -0500 m3 commit 09627479545123f87ad603bfc6a0249d2b601b35 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1
The idea is now to complete the set of commits on the master branch. We are missing m3.
We first check the state on the master and then the feature branch. All seems to be as expected.
The index.html file associated with the master branch is edited by adding the string “m3”. We then commit the change using the label “m3”. We display the status of the main branch and verify that it matches our diagram.
# **** switch to feature to commit f2 **** c:\Temp\GitPlay>git checkout feature Switched to branch 'feature' c:\Temp\GitPlay>git log commit 24ded46eaec4b8c5b467fb549028e5108cf6a19d (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:58:33 2019 -0500 f1 commit 09627479545123f87ad603bfc6a0249d2b601b35 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1 c:\Temp\GitPlay\feature>git status On branch feature Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: ../index.html c:\Temp\GitPlay\feature>git commit -m "f2" [feature da4f148] f2 1 file changed, 1 insertion(+), 1 deletion(-) c:\Temp\GitPlay\feature>git log commit da4f148191a363f6bc2add5d766b4b7fdf99f832 (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 14:25:32 2019 -0500 f2 commit 24ded46eaec4b8c5b467fb549028e5108cf6a19d Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:58:33 2019 -0500 f1 commit 09627479545123f87ad603bfc6a0249d2b601b35 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1
Now it is time to add the last commit labeled f2 to the feature branch. This represents some additional work which concludes the second and last feature.
The process is similar to what we have been doing. We first check things, edit the file, commit and check if all is well.
Like I have stated multiple times, the best way to learn is by experimenting. I made some changes that fall outside of the main scope of this post. You will probably experiment as you go. The following is a set of commands that I use to drop changes to a file before committing.
# **** drop a change **** c:\Temp\GitPlay>git status On branch feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html no changes added to commit (use "git add" and/or "git commit -a") c:\Temp\GitPlay>git stash Saved working directory and index state WIP on feature: da4f148 f2 c:\Temp\GitPlay>git status On branch feature nothing to commit, working tree clean c:\Temp\GitPlay>git stash drop Dropped refs/stash@{0} (db07f07007ec4ed495f001d9d1b7d18026a07020) c:\Temp\GitPlay>git status On branch feature nothing to commit, working tree clean c:\Temp\GitPlay>git checkout master Switched to branch 'master' c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean
In this case I have edited on the feature branch the index.html file. I do not wish to commit such changes. The simplest was I have found to do this is with git stash followed by git stash drop.
# **** this is how we need things to start with (before git merge) **** c:\Temp\GitPlay>git log commit bbf5ed72d70b43808f92baf80772064183d8dd60 (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 14:14:45 2019 -0500 m3 commit 09627479545123f87ad603bfc6a0249d2b601b35 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1 c:\Temp\GitPlay>git checkout feature Switched to branch 'feature' c:\Temp\GitPlay>git log commit da4f148191a363f6bc2add5d766b4b7fdf99f832 (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 14:25:32 2019 -0500 f2 commit 24ded46eaec4b8c5b467fb549028e5108cf6a19d Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:58:33 2019 -0500 f1 commit 09627479545123f87ad603bfc6a0249d2b601b35 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1
We are ready to use git merge. The status of the master and feature branches is as expected. They match the diagram for this post.
# **** git merge **** c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean //$git merge feature c:\Temp\GitPlay>git merge --squash feature Automatic merge went well; stopped before committing as requested Squash commit -- not updating HEAD c:\Temp\GitPlay>git commit -m "feature and master merged" [master a400679] feature and master merged 1 file changed, 1 insertion(+) create mode 100644 feature/index.html c:\Temp\GitPlay>git log commit a4006799874ae0676f3b077084d7eeda8134477f (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 14:48:11 2019 -0500 feature and master merged <==== commit bbf5ed72d70b43808f92baf80772064183d8dd60 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 14:14:45 2019 -0500 m3 commit 09627479545123f87ad603bfc6a0249d2b601b35 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:43:37 2019 -0500 m2 commit 6ef1917475da8b93cc7f8257e5f051ab9a2e8047 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 11:35:28 2019 -0500 m1
We now merge the feature branch into master. When done we check and the results match the diagram as illustrated in the master combined portion.
Now let’s use git rebase and see how we use it and what the results are.
# **** this is how we need things to start with (before git rebase) **** c:\Temp\GitPlay>git checkout master Switched to branch 'master' c:\Temp\GitPlay>git log commit b83e2677b2e26d6e303cb3171a4c23e01134febc (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1 c:\Temp\GitPlay>git checkout feature Switched to branch 'feature' c:\Temp\GitPlay>git log commit 23d547047b37b652206ce601b3ebb79a50204184 (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:11:42 2019 -0500 f1 commit b83e2677b2e26d6e303cb3171a4c23e01134febc (master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1
At this point we have on master commits m1 and m2 and on feature commit f1.
We first edit and commit m3 on the master branch. We verify that all is well. We then edit and commit f2 to the feature branch. The feature branch is displayed and all is well so far. The master branch also seems to be as expected.
# **** rebase on main branch **** c:\Temp\GitPlay>git checkout feature c:\Temp\GitPlay>git log commit 23d547047b37b652206ce601b3ebb79a50204184 (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:11:42 2019 -0500 f1 commit b83e2677b2e26d6e303cb3171a4c23e01134febc (master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1 c:\Temp\GitPlay>git checkout master Already on 'master' c:\Temp\GitPlay>git status On branch master nothing to commit, working tree clean c:\Temp\GitPlay>git log commit b83e2677b2e26d6e303cb3171a4c23e01134febc (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1 c:\Temp\GitPlay>git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html no changes added to commit (use "git add" and/or "git commit -a") c:\Temp\GitPlay>type index.html m1 m2 m3 c:\Temp\GitPlay>git add index.html c:\Temp\GitPlay>git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html c:\Temp\GitPlay>git commit -m "m3" [master a128b66] m3 1 file changed, 1 insertion(+), 1 deletion(-) c:\Temp\GitPlay>git log commit a128b66558351f4cef6c5fa3d749240b38154625 (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:30:58 2019 -0500 m3 commit b83e2677b2e26d6e303cb3171a4c23e01134febc Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1 c:\Temp\GitPlay>git checkout feature Switched to branch 'feature' c:\Temp\GitPlay>git rebase master First, rewinding head to replay your work on top of it... Applying: f1 c:\Temp\GitPlay>git log commit 97d37d187fd6c0cb53be7a606fe84e73dfa4cd5c (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:11:42 2019 -0500 f1 commit a128b66558351f4cef6c5fa3d749240b38154625 (master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:30:58 2019 -0500 m3 commit b83e2677b2e26d6e303cb3171a4c23e01134febc Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1 c:\Temp\GitPlay>git checkout feature Already on 'feature' M feature/index.html c:\Temp\GitPlay>git status On branch feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: feature/index.html no changes added to commit (use "git add" and/or "git commit -a") c:\Temp\GitPlay>git add feature/index.html c:\Temp\GitPlay>git status On branch feature Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: feature/index.html c:\Temp\GitPlay>git commit -m "f2" [feature 35baf08] f2 1 file changed, 1 insertion(+), 1 deletion(-) c:\Temp\GitPlay>git log commit 35baf0890778f5af007bd916b3259f227b6f89d1 (HEAD -> feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:40:57 2019 -0500 f2 commit 97d37d187fd6c0cb53be7a606fe84e73dfa4cd5c Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:11:42 2019 -0500 f1 commit a128b66558351f4cef6c5fa3d749240b38154625 (master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:30:58 2019 -0500 m3 commit b83e2677b2e26d6e303cb3171a4c23e01134febc Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1 c:\Temp\GitPlay>git checkout master Switched to branch 'master' c:\Temp\GitPlay>git log commit a128b66558351f4cef6c5fa3d749240b38154625 (HEAD -> master) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:30:58 2019 -0500 m3 commit b83e2677b2e26d6e303cb3171a4c23e01134febc Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1
We now rebase on master using the feature branch. The idea is to get an updated master branch with all the changes from the feature branch.
# **** rebase on feature branch **** c:\Temp\GitPlay>git rebase feature First, rewinding head to replay your work on top of it... Fast-forwarded master to feature. c:\Temp\GitPlay>git log commit 35baf0890778f5af007bd916b3259f227b6f89d1 (HEAD -> master, feature) Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:40:57 2019 -0500 f2 commit 97d37d187fd6c0cb53be7a606fe84e73dfa4cd5c Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:11:42 2019 -0500 f1 commit a128b66558351f4cef6c5fa3d749240b38154625 Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:30:58 2019 -0500 m3 commit b83e2677b2e26d6e303cb3171a4c23e01134febc Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:05:21 2019 -0500 m2 commit 2b43b486f478a483ac3f8897d0323cacbc23b8cf Author: John Canessa <john.canessa@gmail.com> Date: Mon May 20 15:04:32 2019 -0500 m1
Hope you enjoyed this post. If you have comments or questions regarding this or any other post in this blog, or if you would like me to help with any phase in the SDLC (Software Development Life Cycle) of a product or service, please do not hesitate and leave me a note below. Requests for help will remain private.
Keep on reading and experimenting. It is the best way to learn!
John
Follow me on Twitter: @john_canessa