Some notes about git
. As with all my technical posts, some or all of this may be out of date. Consider it, then, courage to believe that there may be a solution to your problem in terms you can understand.
I have a local repository I want to make into a remote repository
Here’s our local repository:
local $ git init .
local $ git add .
local $ git commit . -m "- initial commit"
Nice. Now make an empty repo on the remote server:
remote $ git mkdir repo1
remote $ cd repo1
remote $ git init --bare .
Now add the remote repo as a “git remote” in your local repo:
local $ git remote add origin ssh://git.foo.com/git/repo1
local $ git remote set-branches origin
local $ git push -u origin master
Unstaging files
Sometimes I accidentally add files to the index, usually a directory at a time:
$ git add newdir
I need to un-add a temporary file or something like that:
$ git rm --cached newdir/tmpfile
This will remove the file from the index.
Resurrecting files
I accidentally did:
$ git rm filename
To get it back, just check it out again:
$ git checkout filename
Replacing the master branch
If you have a branch (yodawg
) you want to make the master branch, do this:
$ git checkout yodawg
$ git merge --strategy=ours --no-commit master
$ git commit -m "- merging yodawg replace into master"
$ git checkout master
$ git merge yodawg
This is from stackoverflow
Merge errors
Sometimes when you do a git pull
, you’ll have conflicts:
CONFLICT (content): Merge conflict in SomeFile
Automatic merge failed; fix conflicts and then commit the result.
Fix the conflict (edit the file), then when you commit, use the --include
(or -i) flag:
$ git commit --include filename
This tells git to add the file into the index first before committing. Once this commit completes, the merge also finishes.
Undoing things
Here’s a great resource.
Local changes during merge
Sometimes when you do a git pull
you’ll have local changes that would be overwritten by the merge:
error: Your local changes to the following files would be overwritten by merge: FILNAME Please, commit your changes or stash them before you can merge. Aborting
To stash your changes for later:
$ git stash save
This will put your changes into a temporary index called the stash. Now you can do your git pull
or merge safely. Once the merge is finished, you can pull your stuff back out again:
$ git stash pop
Branching
You’re hacking away and want to try something radical. Time to branch:
$ git checkout -b my-experiment
Switched to a new branch 'my-experiment'
That was easy.
What about my local changes?
Let’s say you’re hacking away and tried something radical and realized that maybe you should have branched those changes. You don’t want to commit them to the master branch just yet. Stash your changes:
$ git stash save
Saved working directory and index state WIP on master: e3aabe6 -
last commit subject here
HEAD is now at e3aabe6 - last commit subject here
Your uncommitted changes have been saved in the stash. Now make your branch:
$ git checkout -b my-experiment
Switched to a new branch 'my-experiment'
$ git stash apply
# On branch my experiment
# Changes not staged for commit:
...
And now you have a new branch with your uncommitted changes applied to it.
“not on any branch” after “git checkout (commitish)”
You’ve branched without a name. Give it a name with:
$ git checkout -b new-branch-name
Tracking remote branches
Assume you have laptop A with master and experimental branches. You’ve pushed everything to a git server. Now on laptop B you want to “track” the experimental branch:
$ git fetch origin (this pulls down all refs)
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/experimental
remotes/origin/master
$ git checkout --track origin/experimental
Now experimental
is a local branch that tracks/follows the origin/experimental
branch.
Alternatively, you can:
$ git checkout -b experimental origin/experimental
Both of these are equivalent: they create a copy of the remote branch and track the remote branch for changes (you can’t make a remote branch your own, but you can create a copy and track the remote).
github work
A nice summary of the “git flow”
Renaming files on a case-insensitive filesystem
OS X is moderately case-insensitive. It will show you the case of files, etc., but when you’re having the file system look for something by name, any case will do.
I had a file I needed to rename:
lib/BS/API/V1/IPs.pm -> lib/BS/API/V1/Ips.pm
On a case-sensitive file system, it would be easy:
$ git mv lib/BS/API/V1/IPs.pm lib/BS/API/V1/Ips.pm
but in OS X you have to make a temp file; fortunately this does not make any new commits:
$ git mv lib/BS/API/V1/IPs.pm lib/BS/API/V1/Ips.pm.tmp
$ git mv lib/BS/API/V1/Ips.pm.tmp lib/BS/API/V1/Ips.pm
then adjust .git/config
:
ignorecase = true
to:
ignorecase = false
Make your commit now. I think you can change ignorecase
back to how it was before now that your commit it made.
Removing a commit
$ git revert (commit)
Removing a commit from one file in a multi-file commit
$ git diff (sha1)..(sha1)^ -- (filename) | patch -p1
Changed files in git log
To see the changed files in the log:
$ git log --stat
to see a diff:
$ git log -p
Create a branch without a specific commit
If you have master
with commits:
g
f
e
d
c
b
a
and you want to make a new branch without e
, do this:
$ git checkout -b new-branch
$ git revert e
Detach subdirectory into separate git repository
This comes from stackoverflow:
Assume you have repository XYZ
:
XYZ/
-ABC/
-DEF/
-foo
-bar
and you want to pull out ABC
into its own repository with history. Do this:
-
clone the repo locally:
$ git clone --no-hardlinks XYZ ABC $ cd ABC
-
if you have branches you want to preserve, see the stackoverflow article
-
remove everything we don’t want:
$ git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
-
remove backup reflogs:
$ git reset --hard $ git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d $ git reflog expire --expire=now --all $ git gc --aggressive --prune=now
-
remove the subtree from the original repo:
$ cd ../XYZ $ git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD
-
how to now sync the pruned repo? I don’t know
restore one file from stash
Remember that the stash is a branch:
$ git checkout stash@{0} -- path/to/file.txt
github remotes
GitHub provides a special pulls remote “namespace” on the upstream repo, so you can add it as a fetch pattern to your .git/config
like so:
[remote "upstream"]
url = https://github.com/neovim/neovim.git
fetch = +refs/heads/*:refs/remotes/upstream/*
fetch = +refs/pull/*/head:refs/pull/upstream/*
convert a working directory into a bare repository
$ git clone --bare -l repo repo.git
$ rm -rf repo
Last modified on 2012-03-28