I wanted to show my mercurian friends around git, and what better way to do that than by real examples.
This morning I wanted to persist the changes I've been making to pelican-mockingbird theme for use in my own blog. Increased verbosity for illustration purposes.
$ git status # Not currently on any branch. # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: static/css/pygments.css # modified: static/css/screen.css # modified: templates/article_stub.html # modified: templates/base.html # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # templates/disqus.html no changes added to commit (use "git add" and/or "git commit -a")
You may notice I'm "not on any branch" (also called detached head state). This is because I am working inside a submodule of
pelican-themes and the submodule is pinned to a particular commit.
First, I fork
pelican-mockingbird on Github and add my new forked repo as a remote.
$ git remote add mine firstname.lastname@example.org:unthingable/pelican-mockingbird.git
Since I'm not on a branch I need to get on one. I want it to be the
master from my new fork.
First, fetch the state of the new origin:
$ git fetch mine From github.com:unthingable/pelican-mockingbird * [new branch] master -> mine/master
It found one remote branch
master and fetched it under a local alias
mine/master. Now I attempt to checkout the remote branch. This is not the branch I'll be working in, but it is a quick way to bring the working dir into the most current state.
$ git checkout mine/master error: Your local changes to the following files would be overwritten by checkout: static/css/pygments.css static/css/screen.css templates/article_stub.html templates/base.html Please, commit your changes or stash them before you can switch branches. Aborting
OK, apparently I was missing some recent commits and now the incoming changes are conflict with my local changes. Before I risk losing my work, it is time for salvation:
$ git stash Saved working directory and index state WIP on (no branch): 2f4c1b6 update screenshot HEAD is now at 2f4c1b6 update screenshot
Now I can get current:
$ git checkout mine/master Previous HEAD position was 2f4c1b6... update screenshot HEAD is now at fa46a80... Merge pull request #5 from kevmo314/master
So far so good. Let's bring my changes back in:
$ git stash pop Auto-merging templates/base.html Auto-merging templates/article_stub.html CONFLICT (content): Merge conflict in templates/article_stub.html Auto-merging static/css/screen.css Auto-merging static/css/pygments.css CONFLICT (content): Merge conflict in static/css/pygments.css
Even though I popped the stash, the stashed changes is still there. At this point (or any point in the future) I can decide to scrap what I'm doing, go back to the original commit I started working from (
2f4c1b6) and reapply my stashed changes conflict-free. This would fully restore the state I had in the beginning of the post.
I decide to keep the new changes and fix the conflicts. Now my changes are in a happy state and I am ready to make a new commit atop
fa46a80 (the last commit on remote
$ git status # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: static/css/screen.css # modified: templates/base.html # # Unmerged paths: # (use "git reset HEAD <file>..." to unstage) # (use "git add/rm <file>..." as appropriate to mark resolution) # # both modified: static/css/pygments.css # both modified: templates/article_stub.html # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # templates/disqus.html
Let's tell git my conflicts are resolved, and also add the new template:
$ git add templates/ static/
(channeling Gallagher) Can it be that easy? Yes, it's that easy!
$ git status # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: static/css/pygments.css # modified: static/css/screen.css # modified: templates/article_stub.html # modified: templates/base.html # new file: templates/disqus.html
Now we're ready to commit and push. But wait, we're still not on any branch. Let's take our current state and make a new branch out of it. I don't want to touch my
master just yet, just in case I bork something — after all, I have been doing mercurial for a few months now...
$ git branch * (no branch) master $ git checkout -b new-master M static/css/pygments.css M static/css/screen.css M templates/article_stub.html M templates/base.html A templates/disqus.html Switched to a new branch 'new-master' $ git commit -am 'fix.' [new-master e542d31] fix. 5 files changed, 125 insertions(+), 82 deletions(-) rewrite static/css/pygments.css (98%) create mode 100644 templates/disqus.html $ git log commit e542d311cf1a6ed318c1807a118a7f4a5ce93f80 Author: unthingable <email@example.com> Date: Tue Nov 5 10:08:43 2013 -0800 fix. commit fa46a8024ceb821a8717ed36f7b9d2a6a06d2060 Merge: decd2d4 7ea3637 Author: william light <firstname.lastname@example.org> Date: Sun Oct 13 06:02:45 2013 -0700 Merge pull request #5 from kevmo314/master use more standardized strftime formats
Looking good! Now I want to take
new-master and push to my github
master without renaming. Can it be that easy?
$ git push mine new-master master Counting objects: 18, done. Delta compression using up to 2 threads. Compressing objects: 100% (9/9), done. Writing objects: 100% (10/10), 2.28 KiB, done. Total 10 (delta 5), reused 0 (delta 0) To email@example.com:unthingable/pelican-mockingbird.git * [new branch] new-master -> new-master
Oops, it's been a while and I forgot the proper syntax. Now there is a branch called
new-master on github. Let's fix and clean up:
$ git push mine new-master:master Total 0 (delta 0), reused 0 (delta 0) To firstname.lastname@example.org:unthingable/pelican-mockingbird.git fa46a80..e542d31 new-master -> master $ git push mine :new-master To email@example.com:unthingable/pelican-mockingbird.git - [deleted] new-master
All done. I still have a local
master that I don't need anymore, so one more thing to tidy up:
$ git branch -av master fa46a80 Merge pull request #5 from kevmo314/master * new-master 51e3737 readme remotes/mine/master 51e3737 readme $ git branch -d master Deleted branch master (was fa46a80). $ git branch --move master $ git branch -v * master 51e3737 readme