Modifying Git History with Git Rebasing and Git Amends
Tags: osd600
Published: 2023-10-11 21:00:03

### Modifying Git History

In Open Source Development, we'll eventually encounter projects with guidelines on how they want their git history and commits to look like. Some guidelines include:
- Writing commits messages a certain way
- Restructuring commits so that there are fewer

Additionally, some guidelines may require a topic branch (branch with bugfix or feature) be updated with the latest changes in a project before a Pull Request is submitted.

### Clean Git History
There are two commonly used tools to achieve clean git histories:
1. Amended commits (`git commit --amend`)
2. Rebasing (`git rebase <branch-to-use-as-new-base>`)

#### Amended Commits 
Amended commits allow you to amend a previous commit with a new message or new staged changes. This is useful if your commit message didn't follow a project's commit guideline, if you have a typo in the commit message, or if you forgot to stage changes in your commit. However, if you are locally amending a commit you that was already pushed to GitHub, pushing the amended commit will be rejected due to a `non-fast-forward`. If you need to push an amended commit that was already pushed to GitHub, you will have to force-push it, using `git push origin <branch-with-amended-commit`. Forcing pushes is dangerous as it will overwrite what is on GitHub. However, they can be safe when you're working inside a pull request or a branch only you own and work on. I've been taught to never force a push on a master branch or a share branch, but it's safe to use if you're working alone on a topic branch for a feature or bug fix.

#### Git Rebase
If you started contributing to an open source project a month ago, chances are when you are ready to make your Pull Request your fork will be behind the master branch. `git rebase` is a way to apply your changes on the updated master branch submitting a pull request or merging the branch. `git rebase` is good for reducing commit messages and makes a project's git history look cleaner than it would be by merging alone.

Git Rebases are commonly done interactively either in vim (default) or a [code editor](https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git) (requires integration/association). On my local machine I associated Git with Visual Studio Code by running:
```
git config --global core.editor "code --wait"
```

### Refactoring ctil

#### Technical Debt
As a program evolves and new features are added, the code becomes more complex, and it becomes easy to lose control of the code. Quickly extending software without managing code quality incurs `technical debt`, as the code will require time to be improved.

#### Refactoring
Refactoring is one technique for improving the structure and maintainability of code _without_ altering its behaviour. No features will be added or bugs fixed, only the code quality will be improved. In my lab exercise I learned four (4) ways to refactor an d improve code:
1. [Extracting functions](https://refactoring.com/catalog/extractFunction.html)
2. [Extracting classes](https://refactoring.com/catalog/extractClass.html) to avoid duplication
3. [Renaming variables] to avoid 'bad code smell' (https://refactoring.com/catalog/renameVariable.html)
4. Splitting code into multiple files

#### Refactoring Process
For my lab exercise, I refactored the main file in ctil, `source.cpp`. It's clear to me that I incurred a lot of technical debt as features were added to ctil. Although I initially created modules to contain related methods, the `main()` method in `source.cpp` is still too large. Refactoring and reducing the complexity of the `main()` method was my main goal for this lab exercise. To this end, I made the following changes to the `main()` method in `source.cpp`:
1. Extracted file extension boolean variables into two methods
2. Renamed variables in extracted methods
3. Extracted directory creation logic into a new module, `fileHandler`

##### File Extensions
Currently, `ctil` is programmed to convert `.txt` and `.md` files to `.html` files. The `main()` function previously checked for these extensions and stored them in boolean variables. Instead of storing these variables in `main()`, I extracted them into two methods in the `ctil module`:
- `ctil::has_txt_suffix`
- `ctil::has_md_suffix`

These methods check if a filepath has either extension, both stored as strings in the methods. These strings were formerly called `md_suffix` and `txt_suffix`, but were renamed to `suffix_md` and `suffix_txt`. It just felt better to have the common word(s) at the beginning of the variable names, and although I don't expect to add more file extensions to `ctil`, this might be a better naming convention for future maintainability.

##### File Handling
`ctil` stores generated files in a folder called `ctil` by creating  a folder using the [filesystem library](https://en.cppreference.com/w/cpp/filesystem), but this logic is also inside the `main()` method. It would be better to extract this logic to a new method and new module, so I created a new module called `fileHandler` and extracted this logic into a method called `fileHandler::initializeDirectory()`. The `main()` still contains file handling logic that can be extracted into functions, but I think this was a good start.


##### Interactive Rebase
After refactoring my program, I had little trouble doing an interactive rebase, as my master branch didn't change at all since I started refactoring on another branch. I was able to squash all my commits using Visual Studio Code. Since I was able to rebase my topic branch, I also had little trouble using Git to change my project's history. During the rebase I did not find any bugs or break my program, however I noticed many ways I could further refactor the `main()` method.