On Tue, Sep 04, 2012 at 01:22:47PM -0700, kramer.newsreader wrote:

> First, let me preface this post by saying that yes I am new to git and that 
> it has by far the steepest learning curve of any source control system I 
> have used.

I think you could have omitted this remark without any loss for your
question, really.

> My question is a two parter.
> 
> 1) I am working in a slightly different environment than my colleagues and 
> need changes to the source in order to build.  Yes, there are probably ways 
> to refactor our code to alleviate this problem at least somewhat, but I am 
> the new guy and that's political (don't get me started).  Anyway, I would 
> like to set up some sort of SANE system such that whenever I fetch, I can 
> apply my changes without adding them to the change list so as NOT to commit 
> them.

This situation calls for using rebase.  More on this below, after
dealing with the problem at hand.

> 2) I thought I could use git stash for this, so I did this:
> 
> git stash --include-untracked
> 
> and when I do
> 
> git stash show
> 
> it shows this:
> 
> backend/infinispan-rar/pom.xml                     |   12 ++++++++++--
> backend/pom.xml                                    |   13 +++++++++++--
> backend/test/pom.xml                               |    3 +--
> .../main/resources/com/mojiva/testDbContext.xml    |    6 +++---
> data/mojiva.xml                                    |    2 +-
> dbmigration/pom.xml                                |   16 ++++++++++------
> .../main/resources/db/changelogs/issue-17544.xml   |    4 ++--
> pom.xml                                            |   11 +++++++++++

Apparently, `git stash show` does not show the "differences" (wholly
added files) which would be introduced by the included untracked files.
I'm not sure about this (never used `git stash` with untracked files
myself) but possibly this is an interesting topic to bring on the main
Git list.

>From what I see with my version of Git (1.7.10), if you tell `git stash`
to include untracked files, the commit representing the stashed state
has three parent commits (as opposed to just two, as usually), and that
extra commit contains all the untracked files.  Supposedly this is a
part of explanation of why these files are not shown.

If you want to see, graphically, how your stash looks, either run

$ gitk --all
or
$ git log --all --graph --decorate --oneline

and you will see a commit, which is one of the stash commit's parents,
titled something like "untracked files on <branchname> ...".
You can notice its SHA-1 name and call, say, `git show` on it to see
your untracked files.

> but when I try to retrieve them, it doesn't work:
> 
> backend/activator/effective.pom already exists, no checkout
[...]
> run/linksDB.script already exists, no checkout
> Could not restore untracked files from stash

Clearly, the files listed do really exist in your checkout (Git work
tree).  If Git were to replace them, you could have lost valuable data.
One straightforward solution seems to be pretty obvious: move the files
listed so some safe place and then retry `git stash apply` -- it should
complete OK (modulo possible conflicts when applying the changes in
tracked files).

You can also directly get the contents of any untracked file recorded
in your stash by referring to that special commit holding them I
described above.  Either dig that commit's SHA-1 name and use it, or
just refer to it by its symbolic name -- since it's the third parent of
the topmost stash, it can be referred to as stash@{0}^3 and hence to get
the contents of the "backend/activator/effective.pom" file you could run

$ git show stash@{0}^3:backend/activator/effective.pom

> I really need these files back and stash won't give them back!

`git stash` is just being cautious about your own data.
I hope I managed to explain how to resolve your problem.

Now let's discuss that "rebase" thing I mentioned earlier.

While there's nothing wrong with stashing, your use case seems to be a
subject for rebasing workflow.  The basic idea is this:
1) You start with a clean state of the branch you're working on,
   without applying your specific local changes.
   Then you fork a local branch off it.
2) You check out that branch and add all your local changes (including
   those extra files which are untracked by now).
   You can do a single commit or a series of commits, this does not
   matter.
   Now this local branch contains all the history of its base branch
   plus one or more commits representing your local changes.

Now, instead of `git pull` you do `git pull --rebase` and after

$ git fetch

instead of

$ git merge --ff origin/base

you do

$ git rebase origin/base

Basically, rebasing this way will make sure your local branch always
contains the history of its base branch + those local commits on top.

A somewhat tricky part comes when you need to make changes to a file you
have tweaked locally *and* you need to send these changes "upstream".
In this case you record these changes normally -- their commits end up
after those "tweak" commits in the line of history -- and then rebase
your branch again, reordering the commits in a way so that these commits
to be shared end up being before the "tweak" commits.

Suppose, your (rebased) branch looks like this:
...->B1->B2->T1->T2
("B" refers to base commits and "T" to your local "tweak" commits).
Now you have recorded two new commits:
...->B1->B2->T1->T2->M1->M2
The idea now is to run
$ git rebase -i B2
to drop into a text editor showing you the rebase script and move the
lines referring to M1 and M2 so that they're placed before T1 in the
history.
After you quit the editor, `git rebase` will proceed and rewrite your
branch to look like
...->B1->B2->M1'->M2'->T1'->T2'

Now you should either `git push <remote> M2':base` directly or first
merge (with --ff, just to be sure) M2' to a local branch which represents
the "pristine" base branch, and then push the changes.

Read more on rebasing:
http://git-scm.com/book/en/Git-Branching-Rebasing
http://git-scm.com/book/en/Git-Tools-Rewriting-History

-- 
You received this message because you are subscribed to the Google Groups "Git 
for human beings" group.
To post to this group, send email to git-users@googlegroups.com.
To unsubscribe from this group, send email to 
git-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/git-users?hl=en.

Reply via email to