I have a git repo created with the --serparate-git-dir
option. I often use the same repo form different working trees by specifying --git-dir
and --work-tree
as arguments.
I have two working trees I switch between frequently so I added a .git
file in the secondary work tree pointing to the repository directory. However since the repository's config
file points to the primary working tree, I still have to specify it explicitly, otherwise it uses the primary working tree.
I tried setting the value of worktree
to $PWD
int the .git/config
file but this causes the following error:
fatal: Could not chdir to '$PWD': No such file or directory
Is there a way to make worktree
dynamic?
Git always runs inside a bash shell, and uses a number of shell environment variables to determine how it behaves. Occasionally, it comes in handy to know what these are, and how they can be used to make Git behave the way you want it to.
To set the Git environment variable, Git provides the git config tool. All the Git global configurations are stored in a . gitconfig file. This file you can easily locate in your system's home directory.
In order to expand environment variables you have to pre-process the Git config file yourself, i.e. by creating a template file, and expand variables with a script before copying the file to your $HOME directory.
I had a similar problem in that I wanted to make my ~/.gitconfig
portable across platforms, so that I could use the same gitconfig on my Macbook and in my Linux VM. I needed credential.helper
to be different depending on the platform.
I ended up writing a little generate_gitconfig
script, and add it to my bashrc so that ~/.gitconfig
was generated automatically upon starting each shell session.
Writing your gitconfig via a script gives you more flexibility in that you can set values dynamically based on environment variables, whether certain commands are installed, the hostname of the machine, etc.
Here is my generate_gitconfig
script, as an example:
#!/bin/bash
cat <<EOF > $HOME/.gitconfig
# This gitconfig was generated via ~/.bin/generate_gitconfig.
# Edit that file, not this one!
[user]
name = Dave Yarwood
email = [email protected]
[push]
default = simple
[core]
autocrlf = input
editor = nvim
excludesfile = $HOME/.gitignore_global
[rerere]
enabled = true
EOF
if [[ "$(uname)" == Darwin ]]; then
CREDENTIAL_HELPER="osxkeychain"
elif [[ -n "$(which gnome-keyring-daemon)" ]]; then
CREDENTIAL_HELPER="/usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring"
fi
if [[ -n "$CREDENTIAL_HELPER" ]]; then
cat <<EOF >> $HOME/.gitconfig
[credential]
helper = $CREDENTIAL_HELPER
EOF
fi
EDIT 05-2016 As @amynbe comments, git >= 2.5 has git-worktree https://git-scm.com/docs/git-worktree
I have a script that someone on freenode passed around, I'm not sure of the author but I know I can share, it is used to create different working copyes based on branches, I think it could fit your use case:
#!/bin/sh
usage () {
echo "usage:" $@
exit 127
}
die () {
echo $@
exit 128
}
if test $# -lt 2 || test $# -gt 3
then
usage "$0 <repository> <new_workdir> [<branch>]"
fi
orig_git=$1
new_workdir=$2
branch=$3
# want to make sure that what is pointed to has a .git directory ...
git_dir=$(cd "$orig_git" 2>/dev/null &&
git rev-parse --git-dir 2>/dev/null) ||
die "Not a git repository: \"$orig_git\""
case "$git_dir" in
.git)
git_dir="$orig_git/.git"
;;
.)
git_dir=$orig_git
;;
esac
# don't link to a configured bare repository
isbare=$(git --git-dir="$git_dir" config --bool --get core.bare)
if test ztrue = z$isbare
then
die "\"$git_dir\" has core.bare set to true," \
" remove from \"$git_dir/config\" to use $0"
fi
# don't link to a workdir
if test -h "$git_dir/config"
then
die "\"$orig_git\" is a working directory only, please specify" \
"a complete repository."
fi
# don't recreate a workdir over an existing repository
if test -e "$new_workdir"
then
die "destination directory '$new_workdir' already exists."
fi
# make sure the links use full paths
git_dir=$(cd "$git_dir"; pwd)
# create the workdir
mkdir -p "$new_workdir/.git" || die "unable to create \"$new_workdir\"!"
# create the links to the original repo. explicitly exclude index, HEAD and
# logs/HEAD from the list since they are purely related to the current working
# directory, and should not be shared.
for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn
do
case $x in
*/*)
mkdir -p "$(dirname "$new_workdir/.git/$x")"
;;
esac
ln -s "$git_dir/$x" "$new_workdir/.git/$x"
done
# now setup the workdir
cd "$new_workdir"
# copy the HEAD from the original repository as a default branch
cp "$git_dir/HEAD" .git/HEAD
# checkout the branch (either the same as HEAD from the original repository, or
# the one that was asked for)
git checkout -f $branch
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With