DEV Community

Cover image for Open Source: Rewriting git history(amend/rebase)
MizuhoOkimoto
MizuhoOkimoto

Posted on

Open Source: Rewriting git history(amend/rebase)

It's Friday which means... it's Blog Time! So many due dates!🙉
This week, I would like to introduce how to refactor my Static Site Generator(SSG) project, and also what I did for practice by using git amend and rebase.

Refactoring my SSG

Refactoring means not changing code, but making existing code easier to read, maintain, and more modular.
In fact, my SSG project had a lot of duplication, and there were a number of conditional templates, which was very inconvenient when adding new features and maintenance.
Link: my SSG project repo

What I did

  1. Added a yargsConfig.js file to keep yargs separates from the main js file.
  2. Added a tempGenerator.js file and created a function to avoid redundancy in the main js file.
  3. Replaced the code to call the function created in step2 in the pajama-ssg.js (main) file.

My redundancy code

var language = argv.l?argv.l:"en-CA";
  if (argv.s == undefined) {
    var template = `
    <!doctype html>
    <html lang="${language}">
     <head>
     <meta charset="utf-8">
     <link rel="stylesheet" type="text/css" href="please_add_your_css_path" />
     <title>${title}</title>
     <meta name="viewport" content="width=device-width, initial-scale=1">
     </head>
     <body>
     ${titleName}
     ${text}
     </body>
    </html>`;
   } else {
      var template = `
      <!doctype html>
      <html lang="${language}">
       <head>
       <meta charset="utf-8">
       <link rel="stylesheet" type="text/css" href="${argv.s}" />
       <title>${title}</title>
       <meta name="viewport" content="width=device-width, initial-scale=1">
       </head>
       <body>
       ${titleName}
       ${text}
       </body>
      </html>`;
  }
Enter fullscreen mode Exit fullscreen mode

I had this code for each condition (This is when a user enter '-l' as an argument, so I had 3 more...)

My new function

module.exports = tempGenerate = (argv_s, argv_l, title, titleName="", text) => {
let style = argv_s ? `<link rel="stylesheet" type="text/css" href="${argv_s}" />` : `<link rel="stylesheet" type="text/css" href="please_add_your_css_path" />`;
let lang = argv_l ? `<html lang="${argv_l}">`: `<html lang="en-CA">`;
let titleLine = title ? `<title>${title}</title>` : "";

var template = `
   <!doctype html>
   ${lang}
   <head>
   <meta charset="utf-8">
   ${style}
   ${titleLine}
   <meta name="viewport" content="width=device-width, initial-scale=1">
   </head>
   <body>
   ${titleName}
   ${text}
   </body>
   </html>`;
    return template;
}
Enter fullscreen mode Exit fullscreen mode

With this one function, I was able to remove the duplicate template in the main ssg and replace it with a single line of code to call the function.

Creating a branch for refactoring and committing

Before working on refactoring

Before I started, I made sure if I had everything from GitHub and it was up-to-date.
$git checkout main
$git pull origin main
I created a branch for refactoring.
$ git checkout -b refactoring

Testing and Committing

When I successfully added files and the function, I made a commit every time.
Added files:
$ git add <fileName>
Made 4 commits:
$ git commit -m "Add yargsConfig file"

After committing, before pushing

Time to rebase!
$ git rebase -i
I used squash and melded into previous commit. Below is what I did and the display on the terminal:
I changed from 'pick' to 's' and 'squash' to squashing!

pick 563d8dd Add yargsConfig file
s 0922645 Add a function and make tempGenerator
squash 48b0fd0 replace code to call function
# Rebase 04a71d5..48b0fd0 onto 04a71d5 (3 commands)
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here THAT COMMIT WILL BE LOST.
Enter fullscreen mode Exit fullscreen mode

When I saved, I used Ctrl+o and exit with Ctrl+x.
It successfully rebased and git created a new commit!

pick 9a1ea54 Add yargsConfig file
Rebase 04a71d5..9a1ea54 onto 04a71d5 (1 command)
Enter fullscreen mode Exit fullscreen mode

Practicing amend

I could change my commit message by using $ git commit --amend.
Also, I learned $git --amend --no-edit command from my professor. This is where I want to update the previous commit to add/change something, but don't want to change the commit message (--no-edit means leave the commit message as it is).

Ready to merge!

I went back to my main branch, and I merged and pushed this refactoring!

Conclusion

I focused on getting rid of the 4 templates in my main js file to improve my project. I had many conditions based on the user input (if a user use -i or -s or -l or none). However, implementing a function made it easier to read since I added a condition in the separate file.
Rebasing and amending are very powerful and useful, and every time I learn about Git, I find it's very interesting. One of my goals through this course is becoming a Git master, so I hope I'm getting close to it!🧙🌟

(Photo by Hello I'm Nik on Unsplash)

Discussion (10)

Collapse
lucassperez profile image
Lucas Perez

Nice, I find git really great! Other useful actions to use during git rebase -i are the fixup and reword (or just f and r, respectively).

Fixup is the same as squash, but it just keeps the message of the commit "receiving" the changes from the other commit. By doing this, it will not ask you for the final commit's message (what is going to be left after all the squashes).

Reword simply opens the editor so you can change the message (like it would happen with an ammend, but you can do it now, during the rebase).

When we simply squash, in fact, we have the opportunity to change the final commit's message during that screen where it shows all the messages from all the commits, like here

# This is a combination of 3 commits.
# This is the 1st commit message:

A simple commit message

# This is the commit message #2:

Another simple commit message

# This is the commit message #3:

Yet another simple commit message

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
Enter fullscreen mode Exit fullscreen mode

Whatever you write at the spot of the 1st commit message will stay as the final commit's message. If you leave it blank, it will use the second if I'm not mistaken, but if you erase all of them, the rebase will fail (might have to double check).

I myself have always found using the squash to edit messages a little weird, and my rite when I want to squash things is to combine fixup with reword, like this:

$ git rebase -i 8aacce3^

reword 8aacce3 A simple commit message
fixup 41e00c3 Yet another simple commit message
fixup 09a149d Another simple commit message   
Enter fullscreen mode Exit fullscreen mode

There's also this guide (kind of like a game) to learn in a more visual way about git branches:
learngitbranching.js.org/

Collapse
okimotomizuho profile image
MizuhoOkimoto Author • Edited on

Thank you for your comments and suggestion! The guide is very interesting and easy to undestand with the visual! I will try to use and see fixup next time😃 Obrigada!

Collapse
blackr1234 profile image
blackr1234

I don't quite understand the "Ctrl+o and exit with Ctrl+x" part. Why do you need to press them? For me, in both Windows and macOS, I save with :wq (vim) in git CLI.

Collapse
lucassperez profile image
Lucas Perez

Nano is the default git editor (at least it was for me), and those are the commands to save and exit, respectively, in it.

Collapse
okimotomizuho profile image
MizuhoOkimoto Author • Edited on

Thank you, Lucas. As you said, I used Window Powershell and nano.

Collapse
blackr1234 profile image
blackr1234 • Edited on

Oh I see, nano has a different interface, with keyboard shortcuts listed at the bottom. My Git isn't using nano. I think it's using vi.

Collapse
shubhamkumar10 profile image
Shubham Kumar

Great going! You can read more about git rebase here: Git rebase vs GIt merge

Collapse
okimotomizuho profile image
MizuhoOkimoto Author

Hi Shubham, thank you for your comment! That's a great blog and easy to understand with the pictures!

Collapse
aboss123 profile image
Ashish Bailkeri

Nice explanation. It' really useful to have the steps in there too.

Collapse
okimotomizuho profile image
MizuhoOkimoto Author

Thank you for saying so, Ashish! This is also my own memorandum, as I easily forget it 😄