Are git commands supposed to be run under the working directory directly? - linux

Suppose I have a git working directory, i.e. the directory which has a subdirectory called .git.
I wonder if the current directory matters when I run a git command.
Is it okay to run a git command
directly under the working directory
directly under some subdirectory of (subdirectory of) the working directory
directly under the parent directory of the working directory?
Consider
git commands which can take an argument which specifies some files, e.g. git add, and
git commands which doesn't take an argument that specifies some files, e.g. git pull, git push.

directly under the parent directory of the working directory?
Actually you can run it anywhere you want as long as you reference the git repo:
git --git-dir=/path/to/my/repo/.git add .
That means wherever you are (.: current folder) will be considered as your working tree. A
You can even specify your working tree:
git --work-tree=/a/path --git-dir=/path/to/my/repo/.git add .
In that latter case, you even can execute that last command anywhere you want. The '.' will be the work-tree /a/path.
Since git 1.8.5, you also have the -C option:
git -C /path/to/my/repo add .
Again, you can execute it anywhere you want, but the command will internally do a cd /path/to/my/repo first, and then execute the add .. That means the '.' will actually be /path/to/my/repo.
Finally, since git 2.5, a git repo supports multiple working trees, so you may execute your command in a folder which does not include a subfolder .git (but actually a kind of symbolic link to /path/to/my/repo/git)

It's OK to run both type of commands in both
directly under the working directory
directly under some subdirectory of (subdirectory of...) the working directory
Note, that you should use paths relative to directory where you are
You can't (by default) run any git command in parent directory. You'll get a message that you aren't in any repo.

I wonder if the current directory matters when I run a git command.
It does. git searches the current working directory for the .git subdirectory, and if it doesn't find it then it searches the parent directory, and so on until it finds it.
directly under the working directory
Yes.
directly under some subdirectory of (subdirectory of) the working directory
Yes.
directly under the parent directory of the working directory?
No, not by default. It is possible to tell git where to find the .git directory so that it doesn't search, but this is not the usual mode of operation.
Documentation on the relevant environment variables:
GIT_DIR is the location of the .git folder. If this isn’t specified, Git walks up the directory tree until it gets to ~ or /, looking for a .git directory at every step.
GIT_WORK_TREE is the location of the root of the working directory for a non-bare repository. If not specified, the parent directory of $GIT_DIR is used.
Source
git commands which can take an argument which specifies some files, e.g. git add, and
These commands need to know both where the .git directory is and the relative position of paths in the work tree.
git commands which doesn't take an argument that specifies some files, e.g. git pull, git push.
Commands like git push or git fetch need to know where the .git directory is, but don't care about the work tree. git pull does since it does a git merge which modifies files in the working tree.

Related

Git tracking to wrong local directory

I created a new directory 438-healthme and cloned a repo into it.
When I index into that directory on the master branch and run a git status it lists all of my computer's files as untracked (see screenshot).
It seems like I set up git wrong a few years ago--is there a way to fix this?
You must have run git init in a folder. You need to find it and run rm -r .git.
Try again, removing that folder, and recreating it with:
git clone https://url/remote/repo 438-healthme
Then, in 438-healthme, there should be a .git subfolder, which means a git status (in the newly created 438-healthme folder) will show you files only from 438-healthme.

What mechanism does git use to find its repository?

I have several git repositories. One of these is in $PATH. Today, I accidentally moved to a directory that I thought had a git repository, but did not have one.
cd <another_directory_without_.git>.
So, when I entered git status, the output was confusing.
It appears git found the repository in $PATH, so in this case, git found the repository in ~/bin, which is in my PATH.
Does git search for repositories by looking in $PATH, or is there another search mechanism at work?
I can't find a definitive reference for the actual details, but we can infer most of it from the documentation to the git repository variables.
Git looks for its a repository, by order of preference:
in a directory provided by the --git-dir argument
in a directory provided by the GIT_DIR environment variable
in subdirectory .git or the current directory
in subdirectory .git of an ancestor directory. Environment variables GIT_CEILING_DIRECTORIES and GIT_DISCOVERY_ACROSS_FILESYSTEMS set a few constraints on that.
According to the git(1) manual page, Git goes like this when it looks for its object store:
If the "--git-dir" command-line option was specified its value is used to locate the repository.
If the GIT_DIR environment variable is available and set its value is used to locate the repository.
Note that in both of these cases no search/heuristics is done.
Otherwise Git tries to figure out if the current directory is the repository — in case it's a bare repository which has no work tree.
The logic it uses to carry out this task is explained here. To cite it:
Test if it looks like we're at a git directory.
We want to see:
- either an objects/ directory _or_ the proper
GIT_OBJECT_DIRECTORY environment variable
- a refs/ directory
- either a HEAD symlink or a HEAD file that is formatted as
a proper "ref:", or a regular file HEAD that has a properly
formatted sha1 object name.
Failing that, Git tries to find a directory named ".git" in the current directory.
If it succeeds, it uses the test from the previous step to verify if it's really what it was looking for.
If it fails, it ascends one level up — to the parent directory and tries again.
The last two steps are carried out until / on POSIX-like systems or the root of the drive — on Windows is hit (and hence there's nothing to ascent). By default, Git also won't cross the boundary of a filesystem of the current directory.
As you can see, no $PATH is involved: this directory is used only to look up executable programs, and Git has no business with it.

How to make current directory a git working directory

I've written multiple *.cpp files in the location ~/Code/CPLUS before I know the existence of git.
Now I want to use git for version control.
I created a folder ~/git_repo/, and in this folder, I ran git init command. When I tried to run the command git add my_first_c.cpp under the path ~/Code/CPLUS, the following message appeared:
fatal: Not a git repository (or any of the parent directories): .git
Then I typed git init ~/git_repo/ under the path ~/Code/CPLUS, the same error still appeared when git status was typed.
If I type git init under the path ~/Code/CPLUS, the add and commit can be executed. The only problem is that .git is stored in ~/Code/CPLUS/, while I'd like it be stored in ~/git_repo.
My question is how to make the folder ~/Code/CPLUS a working directory while the repo info is stored in ~/git_repo/? And my machine has no GUI.
You could try exporting the variables export GIT_WORK_TREE=~/git_repo/ and export GIT_DIR=../Code/CPLUS from terminal (or in your ~/.bashrc) so Git uses these.
Thanks #Alariva , the suggested solution indeed solved this question. With .git created in ~/git_repo/, typing git --git-dir=/abs/path/to/repo/git_repo/.git add my_first_c.cpp works.
The solution comes from this post.

Git clone without including top/parent folder

We have a repo in git where the project is contained in a folder called Project. We'd like to be able to release the code to a production server, by cloning the repo, without including the "Project" folder, but with everything below it. Is this possible? The destination directory name is /var/www, which is unrelated to anything in the project. Unfortunately I can't just do a symbolic link because of the nature of our hosting provider (which we'll change soon).
My answer take the assumption that you have a git repository whose content is the following:
/.gitignore
/Project
/Project/index.php
/ProjectB
/ProjectB/pom.xml
If you don't need history at all in that copy of your repository, there is the git archive command which can do what you want except its output its data in tar or zip format:
git archive [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]
[-o <file> | --output=<file>] [--worktree-attributes]
[--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
[<path>…]
Like:
git archive --format=zip --remote=git#foobar.git master -- Project | unzip
However, the git clone command does not accept a repository path, and I think it's not really git like to export only a tree view of some branch. You would probably need a submodule making Project an independent git repository, or like the git archive example, get only what you want but without versioning (which can be questionable on a production server).
Instead, you can do that:
Clone your repository to whatever path, say /opt/foobar.
Create a symbolic link of /opt/foobar/Project in /var/www.
Or reference the /opt/foobar/Project in your apache configuration (to avoid the symlink) instead of plain /var/www.

SVN checkout the contents of a folder, not the folder itself

I'm fairly new to linux and svn. I'm trying to checkout the trunk folder of a project into my public_html directory using this command (while in public_html):
svn checkout file:///home/landonwinters/svn/waterproject/trunk
The waterproject directory contains the files from untarring a base install of drupal.
It checks out fine, except all the files are in public_html/trunk instead of just being in public_html.
I don't know the command to move all the contents of trunk up to public_html and rm trunk, but I think I could figure that out relatively easily. I just want to know if I can just check out the contents of a folder, without the folder itself.
Just add a . to it:
svn checkout file:///home/landonwinters/svn/waterproject/trunk .
That means: check out to current directory.
svn co svn://path destination
To specify current directory, use a "." for your destination directory:
svn checkout file:///home/landonwinters/svn/waterproject/trunk .
Just add the directory on the command line:
svn checkout svn://192.168.1.1/projectname/ target-directory/
Provide the directory on the command line:
svn checkout file:///home/landonwinters/svn/waterproject/trunk public_html

Resources