I'm a Systems Reliability and DevOps engineer for Netdata Inc. When not working, I enjoy studying linguistics and history, playing video games, and cooking all kinds of international cuisine.
Two other big ones come to mind that I often see underutilized, but find indispensable on a regular basis:
Interactively stage individual parts of files for a commit
Sometimes, you end up fixing bugs in nearby code that you didn't notice until you were testing something else. Or maybe you end up needing to split out a big bunch of changes into separate logical steps. Or perhaps you just forgot to commit something before starting on the next thing.
In any case, you can use:
git add -i
It will bring up a menu-based interface to step through individual hunks of the current set of changes to the working tree and let you select only the parts you want to include in the commit.
Rearrange (or completely rewrite) the history of a branch
git rebase also has an interactive mode (also enabled with the -i switch). You can use this to edit history back to a certain commit without moving the branch you're on by running:
git rebase -i <commit>
The commit you specify should be the last one before the commit you want to start editing things at. Just like a normal rebase, you can specify a tag or a branch name instead of a commit here (or use a commit-like form like HEAD~8). This will open an editor with a list of instructions to git for how to perform the rebase (it defaults to what it would do if you were doing a regular rebase), as well as some comments below that explaining what each instruction means.
Things you can do with this include:
Change the order of commits. Just reorder them in the list that shows up when you start the interactive rebase.
Completely remove commits from history. Just remove the lines for those commits from the list, or change the pick at the beginning of the lines to drop.
Insert completely new commits. Add a break to the list where you want to put the new commit, the rebase will stop there and drop to a shell, where you can make your code changes and commit them just like normal, then run git rebase --continue to resume the rebase. You can also use this to merge branches or cherry pick commits into arbitrary locations in your history.
Amend commits arbitrarily far back in the history. Replace pick with edit, the commit will be applied, but the rebase will stop immediately afterwards so you can use git commit --amend to update the commit. This is essentially a shorter form of adding a break after the commit.
Squash commits. Put the line for the commit you want to squash right after the one you want to squash it into, then replace the pick with squash.
Meld fixes into the commit they fix. Same as squashing, just use fixup instead of squash and it will just use the commit message from the first commit as-is instead of prompting you to enter a new one for the single commit it produces.
Split commits. Mark the commit you want to split to be amended, then run git reset HEAD~ when the rebase stops to let you amend that commit. This will remove that commit from the history, but leave all the changes it made to the working tree in place, and you can then split them out into new commits however you want (possibly using git add -i to simplify the process).
Verify the code state between commits. You can add a line starting with exec wherever you want in the sequence of commands. The rebase process will pass the rest of that line to the shell to be run as a command (essentially, it calls sh -c followed by the rest of the line) at that point during the rebase, and will stop the rebase if the command fails (just like if a merge failed) so that you can investigate what happened and either cancel the rebase or continue it as you see fit.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Two other big ones come to mind that I often see underutilized, but find indispensable on a regular basis:
Interactively stage individual parts of files for a commit
Sometimes, you end up fixing bugs in nearby code that you didn't notice until you were testing something else. Or maybe you end up needing to split out a big bunch of changes into separate logical steps. Or perhaps you just forgot to commit something before starting on the next thing.
In any case, you can use:
git add -i
It will bring up a menu-based interface to step through individual hunks of the current set of changes to the working tree and let you select only the parts you want to include in the commit.
Rearrange (or completely rewrite) the history of a branch
git rebase
also has an interactive mode (also enabled with the-i
switch). You can use this to edit history back to a certain commit without moving the branch you're on by running:git rebase -i <commit>
The commit you specify should be the last one before the commit you want to start editing things at. Just like a normal rebase, you can specify a tag or a branch name instead of a commit here (or use a commit-like form like
HEAD~8
). This will open an editor with a list of instructions to git for how to perform the rebase (it defaults to what it would do if you were doing a regular rebase), as well as some comments below that explaining what each instruction means.Things you can do with this include:
pick
at the beginning of the lines todrop
.break
to the list where you want to put the new commit, the rebase will stop there and drop to a shell, where you can make your code changes and commit them just like normal, then rungit rebase --continue
to resume the rebase. You can also use this to merge branches or cherry pick commits into arbitrary locations in your history.pick
withedit
, the commit will be applied, but the rebase will stop immediately afterwards so you can usegit commit --amend
to update the commit. This is essentially a shorter form of adding abreak
after the commit.pick
withsquash
.fixup
instead ofsquash
and it will just use the commit message from the first commit as-is instead of prompting you to enter a new one for the single commit it produces.git reset HEAD~
when the rebase stops to let you amend that commit. This will remove that commit from the history, but leave all the changes it made to the working tree in place, and you can then split them out into new commits however you want (possibly usinggit add -i
to simplify the process).exec
wherever you want in the sequence of commands. The rebase process will pass the rest of that line to the shell to be run as a command (essentially, it callssh -c
followed by the rest of the line) at that point during the rebase, and will stop the rebase if the command fails (just like if a merge failed) so that you can investigate what happened and either cancel the rebase or continue it as you see fit.