The Lumber Room

"Consign them to dust and damp by way of preserving them"

Archive for November 2011

My Git personal reference

with 9 comments

Various git things I’ve had to look up from time to time.

(Always, while doing anything dangerous, have a gitk window open. Look, don’t guess. (Haven’t used gitk in a while.) And if you’re sharing your repository publicly, you can forget about most of the below.)

Git reset

What git reset <commit> does:
* Reset HEAD to the given commit
* (If not --soft) copy this new HEAD to the index
* (If --hard) copy contents of index to working dir

So, for example:
* To “undo commit”: git reset HEAD~1
This resets HEAD to HEAD~1, without copying this new HEAD to the index. So it’s as if you didn’t make the commit. You can go and commit in another branch if you want.

Copy commits from another repository

# 1. Add the other repo as a remote
git remote add other_repo_nickname <other repo's path/url>
# 2. Fetch its data. (pull = fetch + merge, so we want only fetch, not pull)
git fetch other_repo_nickname
# 3. The rest should be familiar
git cherry-pick <commit>

Note that you don’t need to specify the remote’s name for cherry-picking. Once you have fetched, all commits, even those originally from the other repo, can be identified just by hash. (If you want to refer to commit by branch, then you can identify it with “other_repo_nickname/branch_name”.)

Swap commits (reorder top two commits)

 git rebase -i HEAD~2 

and in your editor, reorder the two “pick” lines. (See here.)

Recovering commits deleted with reset --hard

In general, these are garbage-collected after 30 days (or when you run git prune or git gc), so you shouldn’t use reset --hard at least without doing a stash first.
If the garbage-collection hasn’t happened yet, get the sha1 hash of the commit with

 git reflog 

then make sure the commit is what you want with

 git show sha1 

and get the commit back with

 git cherry-pick sha1 

(or rebase or merge instead of cherry-pick, if that’s what you want.)

Squashing commits together, to keep your history clean

Use rebase. To squash the last n commits into one, do

 git rebase -i HEAD~n 

and change all “pick”s except the first one to “squash” (or “s”). See here and here.

Delete a specific commit

Use rebase -i, again.

 git rebase -i <commit>~1 

Delete the line for the commit you want deleted. See here and here.

Amend a specific older commit

This is tricky, and I don’t think I’ve seen it anywhere, especially for the case where there are branches that depend on it.
My solution: Find the first branch X that’s downstream from (= later than) it. Keep track of the whole tree downstream from X (take a screenshot if you must); you’ll need it. Checkout X, and do “rebase -i HEAD~[large enough number to cover the commit you want to amend]”. In the editor that pops up, keep all “pick” lines, changing only that one line you want to amend to “edit”. Save and close. Now git has stopped, allowing you to amend that commit. Edit the file. Do “commit –amend” (don’t forget to add all files you want included in that commit!). Do “rebase –continue”. You’re back at X now. Now for the first branch Y that was downstream from X, checkout Y, do “git rebase X”, and recurse on Y.
This doesn’t seem work (gets into rebase conflicts). Need to try again, and ask.


Written by S

Tue, 2011-11-29 at 10:06:52

Posted in compknow

Tagged with