5

Regarding out Git workflow, we create a branch off the master that we use for a specific sprint, and each work item in that sprint branches from it. So effectively, the branch/merge flow would be:

master
  |   \
  |    sprint42________
  |       |    \       \
  |       |     item1   item2
  |       | ___/       /
  |       |/          /
  |       | _________/
  |       |/
  | _____/
  |/
  |

Now, in this flow, it turns out that the changes I made to one of the files in item1 also needs to be done in item2 (think of a utilities file to which I added a handy function).

So, based on the accepted answer for this question, I checked out the item2 branch and proceeded to pull the utilities file from the item1 branch as follows:

git checkout item2
git checkout item1 utilities.xyzzy

However, on checking git status, it appears that this file has been put in the staging area whereas I thought it would make more sense to treat it as a freshly modified file:

pax> git status
On branch item2
Your branch is up-to-date with 'origin/item2'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        modified:   utilities.xyzzy

Why was this done this way? How can I, when pulling a file from a different branch into my current branch, get it to simply be a modified file that I will stage when ready?

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I'd made the same sort of "thinko" at one point and find it helpful to remember that a pull is a fetch/merge/commit (in a fast-forward) and checkout is at best a third of that action. Yes, I know you didn't use `pull` but your original wording suggests one verb might have spilled into the other. – msw Dec 10 '15 at 07:00

2 Answers2

6

Side note: when I read the original subject line "Why is file pulled from ..." (now fixed), I thought you were referring to the git pull script. It's worth emphasizing, I think, that you are referring specifically to git checkout here, used in the form: git checkout branch path.

Consulting the git checkout documentation, we find this:

git checkout [-p|--patch] [<tree-ish>] [--] ...

When <paths> or --patch are given, git checkout does not switch branches. It updates the named paths in the working tree from the index file or from a named <tree-ish> (most often a commit). In this case, the -b and --track options are meaningless and giving either of them results in an error. The <tree-ish> argument can be used to specify a specific tree-ish (i.e. commit, tag or tree) to update the index for the given paths before updating the working tree.

I put the crucial bit in boldface here: git first writes from the given "tree-ish" into the index (if not checking directly out of the index), then copies from the index to the work-tree. This is why the new file is staged. To undo the staging, you must use git reset on the same path.

There is a way to get the file into the work-tree without copying it through the index, using git show:

git show item1:utilities.xyzzy > utilities.xyzzy

The git show command will pretty-print the specified object (in this case, that file) to standard output, and redirecting the output captures the file. Note however that this bypasses any smudge filter that would modify the file's contents on a normal checkout.

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
  • 1
    You posted at the exact same second than my answer ;) But you always get an automatic +1 from me. – VonC Dec 10 '15 at 05:44
  • 1
    Well, you typically get one from me, too. Mutual admiration society, or something? :-) (I'm not so good at +1-ing questions and answers, I do it in fits...) – torek Dec 10 '15 at 05:44
5

As I mentioned in "git reset vs git reset HEAD" for git checkout <tree-ish> -- <paths>.

git checkout <tree-ish> -- <pathspec>

When <paths> are given, git checkout does not switch branches.
It updates the named paths in the working tree from the index file or from a named <tree-ish> (most often a commit).

Since the index is directly updated, you get a file ready to be committed.
Hence the "Changes to be committed:" of the git status.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250