16

I'm writing a Bash script, and I want to checkout a tag and then checkout back to where I started.

I tried git co HEAD@{1}, but when starting at master, that takes me back to the commit SHA of master but with a detatched head.

Is there something like pushd & popd for Git?

Zoe
  • 27,060
  • 21
  • 118
  • 148
ma11hew28
  • 121,420
  • 116
  • 450
  • 651

4 Answers4

28

git checkout @{-1} which can be abbreviated to git checkout -.

From the manpage:

As a special case, the "@{-N}" syntax for the N-th last branch checks out the branch (instead of detaching). You may also specify - which is synonymous with "@{-1}".

wnoise
  • 9,764
  • 37
  • 47
4

EDIT: wnoise's suggestion will work if you don't want to keep an explicit history the way pushd/popd does. If you do (and don't want an ordinary checkout to affect your LRU):

I don't know of anything that will do what you want out of the box, but it's not to hard to hack together something along those lines. If you add a file named git-foo to your PATH, you get a new git foo command. So, git-pushd could look like:

#!/bin/bash

SUBDIRECTORY_OK=1
. $(git --exec-path)/git-sh-setup

git symbolic-ref HEAD | sed s_refs/heads/__ >> $GIT_DIR/.pushd
git checkout "$@"

And git-popd:

#!/bin/bash

SUBDIRECTORY_OK=1
. $(git --exec-path)/git-sh-setup

REF=$(head -n1 $GIT_DIR/.pushd)

[ -n "$REF" ] || die "No refs to pop"
git checkout "$REF" && sed -i -e '1d' $GIT_DIR/.pushd
Walter Mundt
  • 24,753
  • 5
  • 53
  • 61
0

In your script, first save the current branch (like written in this answer):

branch_name="$(git symbolic-ref HEAD 2>/dev/null)" ||
branch_name="(unnamed branch)"     # detached HEAD
branch_name=${branch_name##refs/heads/}

then go and checkout the tag you want to

git checkout -b tag_branch tag_name

Do what you want to do on that branch, then checkout the old branch again:

git checkout $branch_name

That's it.

Community
  • 1
  • 1
eckes
  • 64,417
  • 29
  • 168
  • 201
0

You can also do it with aliases and /tmp/gitStack as a temporary file to track your stack.

Checkout the main aliases I've made:

[alias]
  pushd         = "!f() { _BRANCH=$(git symbolic-ref head); _BRANCH=${_BRANCH#'refs/heads/'}; echo $_BRANCH >> /tmp/gitStack; git checkout $@;}; f "
  pop           = "!f() { _BRANCH=$(tail -1 /tmp/gitStack); git checkout ${_BRANCH%*:}; head -n+1 /tmp/gitStack > /tmp/_gitStack; mv /tmp/_gitStack /tmp/gitStack; }; f"
  pop-clear     = "!f() { rm /tmp/gitStack; }; f"
  pop-list      = "!f() { cat /tmp/gitStack 2> /dev/null; }; f"
aemonge
  • 2,289
  • 1
  • 24
  • 26