2

I'm new to GIT. I create repository with commands:

cd /home/user_name
mkdir repo && cd repo
mkdir site.git && cd site.git
git init --bare

then in the hooks directory, I create the post-receive file and add there:

#!/bin/sh
git --work-tree=/home/user_name/dev.ireserve.com --git-dir=/home/user_name/repo/site.git checkout -f

after that, I add permissions: chmod +x post-receive

at my local machine in the laravel project directory I run:

git init

then I run:

git remote add live ssh://root@example.com/home/user_name/repo/site.git

after that usually:

git add .
git commit -m "my message"

and at the end :

git push live master

but I got a message:

remote: fatal: This operation must be run in a work tree

enter image description here

Why I got this error? What is a problem?

Aleks Per
  • 1,549
  • 7
  • 33
  • 68
  • possible [duplicate](https://stackoverflow.com/questions/1456923/why-am-i-getting-the-message-fatal-this-operation-must-be-run-in-a-work-tree) – Hamza Mohamed Mar 06 '18 at 21:22
  • I don't think that this is depicted. I cant find an answer in the link you posted... Can you please help me to solve this problem? – Aleks Per Mar 06 '18 at 21:26
  • 1
    can you check if you have branches on your machine, `git branch -a` – Hamza Mohamed Mar 06 '18 at 21:31
  • 1
    Use [this guide](https://devmarketer.io/learn/deploy-laravel-5-app-lemp-stack-ubuntu-nginx/) – Kenny Horna Mar 06 '18 at 21:33
  • @HamzaMohamed I got this: C:\wamp\www\mavis>git branch -a * master remotes/live/master C:\wamp\www\mavis> – Aleks Per Mar 06 '18 at 21:37
  • @HCK I follow this https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps – Aleks Per Mar 06 '18 at 21:41
  • I added an answer as apparently the answer that was picked, explains the Q, but doesn't show how to solve or show a toturial .. if you see it a satisfying answer, please mark as solved, otherwise please explain what is missing and I'll update accordingly. – Hamza Mohamed Mar 06 '18 at 21:51
  • I follow many tutorials but I dont know why I got : remote: fatal: This operation must be run in a work tree ... I'm already in a work tree /mavis is my work tree ... there is also folder .git . – Aleks Per Mar 06 '18 at 22:01
  • out of curiosity; why did you add Laravel tag? – Hamza Mohamed Mar 06 '18 at 22:05
  • 1
    my project is Laravel project ... and I have .htaccess file that redirect all to /public folder and maybe .htaceess file makes a problem – Aleks Per Mar 06 '18 at 22:06
  • @AleksPer You steps seems ok. Is the machine with your laravel project different from the machine where site.git repo located? And since you used ssh protocol, please also make sure the ssh key is added in your local machine. – Marina Liu Mar 07 '18 at 07:13
  • my fault... I select wrong folder ... – Aleks Per Mar 07 '18 at 10:53

2 Answers2

2

From the comments, you have 1 directory on both sides, you need to start creating versions so you can use the real power of GIT.

You need to create branches(versions) if you are willing to use GIT add.

check this answer

for adding branches, check this tutorial.

and this is the tutorial from the start.

This is the best tutorial, IMHO; for GIT.

It will save a lot of effort and time.

Happy coding!

Hamza Mohamed
  • 1,373
  • 1
  • 12
  • 28
  • I follow many tutorials but I dont know why I got : remote: fatal: This operation must be run in a work tree ... I'm already in a work tree /mavis is my work tree ... there is also folder .git ... – Aleks Per Mar 06 '18 at 21:58
  • Usually the tutorials are using Gits that have already many branches, as they try to keep the tutorial suitable for every situation. just check the tutorial I have added, if you liked it and wanted to dive more .. you can always check the GIT [Doc](https://git-scm.com/doc) – Hamza Mohamed Mar 06 '18 at 22:02
2

TL;DR: I think a mkdir step is missing from your Laravel setup instructions.


This command:

git init --bare

is meant for making server repositories in which no one will ever do any work.

Now, that might seem an odd thing to do: why create a repository where no one can work on the repository? And it is an odd thing to do, but it exists for a reason.

Bare vs non-bare repository

If you make a repository where you can work:

git init

then you can work in it, but—to oversimplify a bit—no one else should ever just send you their work unannounced. But people also need to share work, and one common usage pattern is that everyone agrees that some work-sharing repository, over on some central server such as the corporate "master source repository" machine, should be the place to which everyone sends work.

At the same time, though, you don't want to have to have someone who spends all day taking people's work into that central repository. You want to let people send their work as soon as it's ready, so that everyone else can go to the central repository to see (or even obtain and use) their work right away. So you need a place that peole can send their work, unannounced, right now.

That's a --bare repository. Since no one works in it, you won't overwrite their in-progress work by sending your completed work.

This is really about the difference between a commit and a work-tree

Making a new commit makes a permanent and incorruptible1 snapshot of your work. But it has to get this from somewhere. The minimum "somewhere" is found in other version control systems as the work-tree: the place you do your work. Git inserts an extra wrinkle here, and forces you to know about it: it adds the index, also called the staging area or sometimes the cache (three names for one thing—it's a very important entity in Git!). The index and work-tree come as a pair, though: they're where you can write things. Commits, once made, are entirely unchangeable, which is what makes them incorruptible. So you need a place to work, where you can both read and write files.

A bare repository holds commits—the read only snapshots—but has no work-tree.2 That's pretty much all there is to it: with no work-tree, there is no place to work. That's what makes it suitable for pushing-to, but without a place to work, you can't do any work in it. You'll need a non-bare repository as well.


1Commits are really only mostly permanent: they last as long as there are names by which one can find them. I'll leave this detail for other tutorials. They are entirely incorruptible though, because the true name of a commit is its hash ID. The hash ID, while quite unpredictable in advance, is a cryptographic checksum of the contents of the commit. If something goes wrong and a commit becomes corrupted, Git will notice, because the contents won't fit the true name hash ID any more.

2For somewhat silly implementation reasons, a bare repository still has an index. It just has no work-tree. They're paired—the index indexes (hence the name) the work-tree—but a bare repository typically still has a completely-empty index it carries around.


Some servers fake up a work-tree for a bare repository

You can combine the bare repository (with no work-tree) with Git's hooks mechanism to create a sort of fake work-tree. This is how your Laravel setup is intended to work, for instance. When your bare server receives a git push, the server runs the hook, and the hook runs git --work-tree=<path> checkout -f to set up a temporary work-tree in <path>. This temporary work-tree is the work-tree for the duration of the one git checkout command. (The index now indexes that temporary work-tree.) Then the git checkout finishes and the bare repository continues to have no work-tree. You still can't work in it.

Note that this last git --work-tree=<path> checkout -f won't create a directory <path>. This directory must already exist. It should initially be empty; after the first git checkout -f, it will contain what git checkout wrote; and on each later git checkout -f, Git will assume (via the index) that it contains whatever the last git checkout -f wrote, and update it in place based on this information.

Hence your original Laravel setup should have had a mkdir home/user_name/dev.ireserve.com in it.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Yes, init your own repository non-bare. Generally you will *clone* some repository (such as the central-server one), so as to start with all their commits, and to convert all their branch names to your remote-tracking names. This `git clone` process will do its own `git init`. Do `git clone` without `--bare` to make your clone non-bare. – torek Mar 06 '18 at 23:24
  • If the repository you clone is completely empty (is a new one created with `git init --bare`), you'll get a warning at the end. In this particular case, you could have just done your own `git init --bare`. But it's better to start with `git clone` (and the warning), I think. – torek Mar 06 '18 at 23:25
  • so at /home/user_name/repo/ to run git clone ? – Aleks Per Mar 06 '18 at 23:26
  • On your machine, wherever you like. Note, by the way, that the hook on the target machine (where you run `git --work-tree= checkout -f`) can't *create* the work-tree directory; it must already exist. That step appears to be missing from your Laravel setup directions. – torek Mar 06 '18 at 23:28
  • but --work-tree=/home/user_name/dev.example.com is there - and there is my laravel project – Aleks Per Mar 06 '18 at 23:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/166359/discussion-between-aleks-per-and-torek). – Aleks Per Mar 06 '18 at 23:31
  • Your work repository and work-tree *must not* be the place that the server dumps its files into. – torek Mar 06 '18 at 23:31
  • It's not clear what's printing `stdin: is not a tty` but whatever it is is trying to do something that doesn't work when not connected to a human. – torek Mar 06 '18 at 23:54