How to Rename a Branch Locally and Remote in Git

This took some googling, so I thought I would document my findings here.

Locally

If you’re already on the branch you’d like to rename, just run:

git branch -m new-name

If you’re on say master, and you have a branch you want to rename now but no checkout, run:

git branch -m old-name new-name

Now that you’ve taken care of your local branch, there’s the unfinished business of mending your remote branch with renaming.

Remote

If you use Github or Gitlab (or whatever) you’re going to want to remove the old-name branch and push the new-name branch:

git push origin :old-name new-name

And finally, push to reset the upstream branch so your local and remote branches are up-to-date:

git push origin -u new-name

How to Move Existing, Uncommitted Work to a New Branch in Git

So here’s a new one for ya.

I was working on a branch all day, closed the laptop, went home and fell asleep. Nothing out of the ordinary. The next day, I awoke, and upon returning to work, immediately began working on a new problem.

The issue arose when I discovered to my horror that I was still on the same branch from yesterday! *Gasp*

Lest we forget, we have Git at our disposal — so I take a breath and dive in:

git status

This will probably return a list of changes not staged like this:

On branch fix-from-yesterday
Your branch is up to date with 'origin/fix-from-yesterday-'.

Changes not staged for commit:
(use "git add …" to update what will be committed)
(use "git checkout -- …" to discard changes in working directory)
modified: project/api-v4.php
modified: web/assets/js/some-project/package.json
...

Now that we have a pulse on things, we can do this:

git checkout -b new-branch-of-changes-for-today

This will leave your current branch as is, create and checkout a new branch and keep all your changes. You can then make a commit with:

git add <the files you want commit>

and finally, commit to your new branch with ol trusty:

git commit -m "Make sure your description is short and sweet"

And there you have it! According to git-checkout documentation, -b and -B are interchangeable. Here’s the rub:

Specifying -b causes a new branch to be created as if git-branch[1] were called and then checked out. In this case you can use the --track or --no-track options, which will be passed to git branch. As a convenience, --track without -b implies branch creation; see the description of --trackbelow.


If -B is given, <new_branch> is created if it doesn’t exist; otherwise, it is reset. This is the transactional equivalent of

How to Delete a Git Commit, Locally and Remote

Alright, we’ve all been there. You got some merge conflicts. Or there’s a last minute hotfix. You feverishly make a commit. Then, your worst fear is realized only after you’ve pushed it remotely.

You made a mistake. The horror.

Horror Omg GIF - Find & Share on GIPHY

First, don’t sweat it. You have options. Most of the time, when I do this, I just need to remove the commit altogether. Other times, I need to make revisions, and replace that commit altogether. Tabula rasa amirite?

Okay so let’s get started. First, I’m making a few assumptions. I’m doing work on a branch separate from master. Let’s say you’re working on Navigation, I would be on a branch called navigation or nav-component or something. It’s good practice to keep your work separate, and branched.

Alrighty, with that out of the way, let’s run git log on our example navigation branch:

$ git log --pretty=oneline --abbrev-commit
32cd83e Made a change with a mistake
b9u3cc5 Changed again
105fd3d Updated some content
5cd7718 Fixed the NavBar
a1842d4 Initial commit

Alright so looking over our log here, we can see at the top, that commit 32cd83e is the most recent commit. It’s the problematic commit in question. To edit out commit history we are going to use rebase:

$ git rebase -i HEAD~2

Before you run this, let’s break down what we’re doing here. A classic use-case of rebase is when you’re on a branch say, navigation. But, let’s say that it’s been a week since you branched. It’s likely that master has diverged since you created your branch. What divergence means, is that the branch (we’re on) navigation is currently out-of-date and lacks the new history (from the past week) on master. We don’t have to worry about that here per se.

But, when you work in repos that multiple people contribute to, a branch can be out-of-date very often. If you use master as the center of truth, the organization can use rebase to bring other contributors history into your branch, and therefor, up-to-date with master. Neat huh?

Anyways, you could say what we’re doing here, is similar. Instead of using rebase to replay work from a branch on top of master, we want to rewrite the commit history of the branch we’re currently on. After running the command above, you should see something like this:

b9u3cc5 Changed again
32cd83e Made a change with a mistake

# Rebase 105fd3d..46cd867 onto 105fd3d
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

Here, (and admittedly confusingly) the most recent commit, 32cd83e we want to destroy is listed at the bottom instead of the top. You can see pretty clearly what the HEAD~2 argument does. It flags rebase to only show the most recent 2 commits in this interactive rebase wizard. Because, that’s all we need to see for context.

So, the options we have now is we can remove that line altogether, and the commit will be dropped into oblivion, as if it never happened. If we remove the problematic commit, and exit the rebase wizard, we can now check our history on navigation:

$ git log --pretty=oneline --abbrev-commit
b9u3cc5 Changed again
105fd3d Updated some content
5cd7718 Fixed the NavBar
a1842d4 Initial commit

Look ma! No mistake! 32cd83e is gone! Now that we have this history locally, let’s push it up, remotely:

$ git push origin +navigation

The + flag before the branch name signals that this will be a force push. Alternatively you could have written the same command as:

$ git push -f origin navigation

I like using this technique, because I enjoy committing everything. Mistakes and all. Because, well for one, why not? Documenting your code history can be helpful sometimes. Besides, ultimately, you can use rebase to squash and fixup your commit history anyways. So, when it comes time to push to remote, I just take a beat and git rebase -i HEAD~N to keep my history lean. I’ve only recently learned the pains of not keeping my git history pretty and concise. So, now I’m a convert, and everyone benefits from a readable git history.

Further Reading:

See the Last 10 Branches You Worked On in Git

As part of my ongoing effort to become more effective at Git, I stumbled into an interesting problem. At Vimeo, we have a lot of branches named after issues reported in Jira. Some branches take on the name of the project or component or a very specific fix. We also have branches that don’t follow naming-conventions at all. It happens. Anyways, somedays, I forget the name of the branches I’ve worked on, say yesterday. Other times, I forgot what work I did on which branch. I grew tired of tab-switching between my terminal and Jira or Github to go and find my work history. I don’t need to see my commits, I just need to see a list of recent branches.

So, I began googling around the web, and came across this post. It’s a good solution I think, David Walsh seems to agree too. Basically, it lists the most recent branches you’ve worked on. But ideally, I’d rather opt for an alias in my .bashrc. I don’t want to clutter up my .gitconfig. That’s, just like my opinion man. Without further ado, here’s my alias in my .bashrc:

# ~/.bashrc

alias recent-branches="git for-each-ref --sort=-committerdate --count=10 --format='%(refname:short)' refs/heads/"

Stupid simple, readable and short. Just the way I like it. There are of course, more complex solutions to this simple problem. But I’m not a huge fan of those longwinded solutions. Anyways, when I run the recent-branches alias in my terminal:

➜  example-repo git:(feature-pages) recent-branches
nav-bar-component-fix
GH-48
features-pages
FR-47
XR-73
VP-71
new-privacy-policy-page
VP-70
VP-49
GH-46

Nifty huh? As you can see, the alias command is really just one long git command. It takes a count=10 flag. So if you need to see more branches in your history, just inflate the value accordingly. Enjoy! ✌️