2

I have embedded Linux system that we want to store in Git. I have installed Git on the system, mount additional USB drive for storing Git data (bare repository). There is no problem with committing and pushing to the remote repository using commands like that:

cd /media/usb
git init --bare
git --work-tree=/ add -A
git --work-tree=/ commit
git --work-tree=/ push -u origin master

But when I clone bare repository to new USB drive and invoke git --work-tree=/ status I see all previously pushed files as deleted, and untracked. How to tell Git to use the work-tree?

Jesper Rønn-Jensen
  • 106,591
  • 44
  • 118
  • 155
user1557654
  • 51
  • 1
  • 5
  • When you say you "see all previously pushed files as deleted, and untracked", do you mean that it shows the work tree as being modified, deleting all the files? – vergenzt Jul 27 '12 at 13:14
  • Yes, exactly it shows it as modified (deleted). – user1557654 Jul 27 '12 at 13:16
  • 1
    http://stackoverflow.com/questions/9745064/using-git-git-dir-path-to-git-pull-path-to-other-bare-git-master-doesnt-a could help here – VonC Jul 27 '12 at 13:36
  • Have you tried just setting the `core.workTree` config variable instead of always passing `--work-tree`? – Lily Ballard Jul 27 '12 at 23:37
  • I think you dont add any files – Oleksandr Pryimak Jul 28 '12 at 02:15
  • Your question is unclear due to some important missing details. You should include a command to set up the `origin` remote on the first USB drive, and also commands to set up the clone on the second USB drive. I managed to reverse-engineer the gaps in order to give my answer below, but you should edit the question for the benefit of other readers. – Adam Spiers Aug 20 '12 at 22:59

1 Answers1

1

The reason you are seeing previously committed files as deleted is that the git index (which is simply a file called index) in the first repository differs from the index in the second repository. The index in the first corresponds to the working tree, whereas the index in the second is uninitialized and therefore has no entries. The output from git status is the result of two comparisons:

  1. between HEAD and the index (to determine staged changes to be committed)
  2. between the index and the working tree (to determine unstaged changes which will not be committed)

In your case, HEAD in the second repository points to a commit which contains all the files you committed from your root filesystem, but the index is empty. So when git performs the first comparison, it thinks that each of these files has been staged for deletion on the next commit.

When git performs the second comparison, it finds that the working tree contains all the same files as the commit, but the index is of course still empty, so it sees these files as "new" untracked files. That is why you see all the files as both deleted and untracked.

The solution is very simple: initialize the second index so that it matches master:

git --work-tree=/ reset

While I'm here, I should point out some other issues with the commands you posted:

  • Firstly, your git add -U is adding all the git repository meta-data files to the repository. In other words, the repository is tracking itself. This is happening as a consequence of the way you use --work-tree, and is very bad. You should ensure that the repository files are ignored by adding them to info/exclude or .gitignore.
  • Secondly, you don't really want a bare repository here, just a detached working tree. You could have achieved this via git config core.bare false and export GIT_DIR=/media/usb; then you could run git commands from outside (i.e. above /media/usb), and you wouldn't have to continually include --work-tree=/ as a global option in each command.

Here's a complete test case which encapsulates everything I just covered except for the second bullet point:

#!/bin/sh

root=fakeroot
mkdir -p $root/media/usb{1,2} $root/{bin,etc}
echo a > $root/bin/sh
echo b > $root/etc/hosts

cd $root/media/usb1
git init --bare

# We don't want our git repository meta-data being tracked.
echo '/media/usb*/' >> info/exclude

git --work-tree=../.. add -A ../..
git --work-tree=../.. commit -m '1st commit'

echo c >> ../../etc/hosts
git --work-tree=../.. add -A ../..
git --work-tree=../.. commit -m '2nd commit'

git remote add origin ../usb2
git --git-dir=../usb2 init --bare

git push origin master

cd ../usb2
echo '/media/usb*/' >> info/exclude

echo "========================================="
echo "index in usb2 is not yet initialized:"
git --work-tree=../.. status
echo "========================================="
echo "initialize index to master (HEAD)"
git --work-tree=../.. reset
echo "========================================="
echo "now we have a clean working tree:"
git --work-tree=../.. status
Adam Spiers
  • 17,397
  • 5
  • 46
  • 65