0

I have a copy of a git working tree without the .git folder. Lets say it was created using following commands:

cd foo
git clone ORIGINURL .
git checkout MYBRANCH
rm -rf .git

It now was changed manually and I want to review, commit and push those changes back to MYBRANCH.

I know I can checkout my branch to some other location and then copy .git folder like so:

cd ../bar
git clone ORIGINURL .
git checkout MYBRANCH
mv .git ../foo/
cd ../foo/
git status
...

Or I can use --work-tree and --git-dir options:

cd ../bar
git clone ORIGINURL .
git checkout MYBRANCH
git --work-tree=../foo --git-dir=.git status
...

Is there and better way to do this (without creating the redundant working tree)? Can I somehow get the .git folder using the --no-checkout option and make it pointing to MYBRANCH without actual checkout?

fsw
  • 3,595
  • 3
  • 20
  • 34

3 Answers3

2

You can treat your current working directory (that is not a Git repository) as a work-tree for a Git repository in some other directory using --git-dir, which is almost the same as what you suggested, but not quite. For instance, suppose you are now in $HOME/foo and you have a clone (with .git directory) in ../bar, or a bare clone in ../bar.git. Then:

git --git-dir=$HOME/bar/.git --work-tree=. status

or:

git --git-dir=$HOME/bar.git --work-tree=. status

will treat your current directory as the work-tree. (Substitute in ../bar as desired—both full and relative paths should work here.) The current branch is still the global current branch for the main repository, though ... and the index for this work-tree is stored in the Git directory, which is not ideal.

This is essentially the same as what you proposed, but with slightly fewer steps. Note that if you do this with a non-bare repository, it does in fact have a work-tree (in this example, in $HOME/bar) and that work-tree will not be synchronized in any way with anything you do in this work-tree (in . aka $HOME/foo).


If you have Git version 2.4 or later (I recommend at least 2.6 or so for this), you can also use git worktree add to create new work-trees outside the "main" work-tree. Each "extra" work tree must be on a unique branch, to avoid the "work-tree becomes stale" problem. Each extra work-tree has its own index as well, which solves the index location issue.

You could do this in $HOME/bar, creating yet a third tree:

git worktree add ../branch

creating $HOME/branch in which branch is checked out (or use -b newbranch to create a new branch as usual, as if via git checkout -b). You can then remove the contents of that directory, except for the .git file (note that this is a file!), and replace them all with the contents of $HOME/bar. You can even shuffle the directory locations around, although this is trickier: see the DETAILS section of the git worktree documentation for more information.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks a lot. Using bare clone as "--git-dir" would certainly be a solution i was hoping for. Unfortunately "git --git-dir=$HOME/bar.git status" throws "fatal: This operation must be run in a work tree" and when i add "--work-tree=." it shows everything as changed. "git worketree" is a very interesting feature however this solution seems more complex than one redundant worktree so i am sticking to solution from your first suggestion. Thanks. – fsw May 18 '17 at 12:45
  • The main problem you run into is that with a bare clone, the index that goes with that bare clone is kept in the bare clone's `git` directory. I'm surprised that you got the `fatal:` gripe; I tested this with my Git (2.12.1) since I thought that might happen. It looks like in my sleepiness I tested it backwards though. I also forgot to mention some index-related issues. – torek May 18 '17 at 20:42
1

The changes were made after .git had been removed, and you didn't make a backup, so now you can't generate the diff and the changes are not tracked. How could you review the changes without the diff?

If you need .git or data of MYBRANCH,

cd foo
git init
git add .
git commit -m 'root'
git tag root
git fetch ORIGINURL MYBRANCH
git checkout -b MYBRANCH FETCH_HEAD
git cherry-pick root

Since the three way merge is not possible in this case, conflicts will come about. After you resolve all the conflicts, the changes are added to MYBRANCH as a new commit. And then git push ORIGINURL HEAD:MYBRANCH.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53
0

To insert a .git directory into a working tree that already exists, I usually do something like this:

https://stackoverflow.com/a/28180781/169947

In short, while in your working tree, you can do:

git clone --bare $URL .git
git config core.bare false
Community
  • 1
  • 1
Ken Williams
  • 22,756
  • 10
  • 85
  • 147