Rebasing
Edit
Uh-oh! You have commited a password in plaintext accidentally. If that wasn't bad enough, you have done this 12 commits ago and only noticed now! Rebasing is the process of fixing that mistake in a way that will make the entire commit history clean again. Via rebasing, you will be able to fix a mistake from multiple commits ago, without touching the other ones.
First, find the commit you want to edit. You will need the the SHA-1 code from the commit directly BEFORE this one. The SHA-1 code is the little identifier code every commit has. For example: 4a4d705. You can look up a list of all commits with the command git log.
Now we will start to rebase! Run this command to start interactive rebasing:
git rebase -i <SHA-1 Code>
This will start the rebasing process. This will open a list of all commits that happened after the one you've been choosing in VIM (What's VIM?). Additionally to the list, you also get to see a list of commands that you can use.
The way this works is basically this: You're building a list of commands that git will then execute one by one during the rebase list. By default, you're seeing that your commits will be listed as pick. This means (refer to the documentation at the bottom) that it will use the commit as is. The list is formatted as <command> <SHA-1> <commit name>.
Now let's assume we have these two commits listed:
pick 023b929 a
pick acd3c4c b
The code we want to take out is in the commit a. To use the command edit (which will allow us to ammend - "fix" - the code), we have to edit this line to say edit instead of pick. Again, this is because right now, we're still just creating the schedule of commands rebase will work through. The rebasing itself has not started yet.
To change the command, we have to enter VIMs text edit mode. To do this, simply press the A key. Now you can edit the code. Navigate to the pick in the first line and change it to edit. When you're done, you can exit VIMs edit mode by pressing ESC.
edit 023b929 a
pick acd3c4c b
Now that we have done this, we can exit VIM altogether and rebasing will start. To exit VIM, type :wq in the Shell while NOT in edit mode.
If you've done everything correctly, you will now see this output in your shell:
Stopped at 023b929... a
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
All files in your repository folder have now been put back to the state they were at the end of this commit. You can now open the files you want to edit and take out that password. Save the file and check the status of the repository with git status. You will see that your changes are tracked as they would with a regular change.
It is not a regular change however! We're gonna follow the instructions from the message above now and, after we run our regular git add ., we're going to use the --amend flag to fix our commit. And after this we want to continue rebasing. So, to do all of that, we run both commands messages above:
git commit --amend
git rebase --continue
If you've done everything correctly you should see a Successfully rebased and updated refs/heads/main. message appear and everything is done!
Merge conflict
Sometimes, especially with small files, git will not be able to automatically recognise what it has to do to make the other commits work after you changed a line. In that case you will have to resolve the merge conflict manually. To do this, open the file in which the conflict happens and navigate to the bit(s) in the code that are enclosed by <<<<<< HEAD >>>>>>. Within these, you fill find the conflicts listed, with a neatly organised "before/after", so you can compare. The before is divided from the after with a bunch of =========. So if we have, for example:
line 1
<<<<<<< HEAD
=======
delete this one
line 2
>>>>>>> (023b929)
We manually edit all of that to say:
line 1
line 2
So we delete all the HEAD tag stuff and look at what we want to keep within that. Then we save the file, run git add <file> and continue with our rebase as normal with git rebase --continue.
Fixup
Another very useful command is fixup. This will combine a commit with the commit before it and only keep that commit's log message. Now what could be a usecase for this? Imagine you have commited a simple typo in the commit a. YOu notice this after creating a commit called b. Now you fix the typo and call it fixup-a. Your commit log should now look like this:
pick 023b929 a
pick acd3c4c b
pick x41h4m3 fixup-a
Now, provided the commit fixup-a only corrects your typo, what you can now do is this:
pick 023b929 a
fixup x41h4m3 fixup-a
pick acd3c4c b
This will essentially correct the typo of commit a - in commit a. This is because as mentioned above, fixup will combine a and fixup-a into one commit - a. The rest of your commit tree will then function as normal and your commit log will look a lot cleaner. It's almost like you never made the mistake in the first place!