Is there a simple command to add a directory and all files underneath it to svn?
I have tried svn add directory which makes sense to me but this doesn’t work as expected. I have googled it and there are solutions which all appear a bit long-winded for something so simple.
What would be the standard way of doing this?
svn add directory only works if the directory hasn't been added already. Adding all new files is not standard operation in svn world. Git does this but that's sidetracking.
You can often get by with svn add directory/* but it misses new files in existing subdirectory. So:
directory/newDirectory/file -> is added
directory/oldDirectory/file -> is NOT added
If you really need to add any file anywhere in the directory hierarchy this one liner will set-up an alias for you to do this:
alias svn_addall="svn st|grep ^?|sed 's/./svn add/'|sh"
Put it into your .profile and you'll have easy access to it any time. :-)
Funny. Which version of svn are you using. I`m on a mac and use svn 1.6. And it works for me.
When i look at my man pages for svn then it looks like the command is recursive by default. You can permit the behaviour with:
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
svn add folder will add the folder and its contents. How doesn't it work as you expect?
Related
I want to have all my configuration files versioned using Git in a remote repository at Github. I'm using Debian 7 testing, and all my configuration files are under the /home/user_name/ directory.
I created the usual .gitignore with all the files that I want to ignore and the files and directories that I want to allow versioning. My problem begins when I go to Documents, for example, and I see in zsh that folder is under the same versioning as the home directory.
I understand that Git works that way, but I need to know if it's possible to avoid that.
One classic way to version configuration files is to create a subdirectory like ~/etc/ and let your ~/.something files be symbolic links to ~/etc/something. Then, you can version ~/etc/ normally.
You can manage to ignore everything but your configuration files, but you'll always have little glitches like: the day you run git clean -fdx in the wrong place, you delete all your data.
Write */ in your .gitignore to ignore directories. Make exceptions with !foodir. Consider prefixing with slashes (see documentation for details).
I have a linux directory (and don't need any windows checkout):
/home/me/projects/project1
In this project, I need SVN (1.8.8) to follow a symlink "link1":
/home/me/projects/project1/link1/<some_directories_and_files>
But SVN won't let me do that, it just add link1 but not its content. If I try to add its content, I get an error:
svn add link1/*
svn: E145001: Can't schedule an addition of '/home/me/projects/project1/link1/first_directory' below a not-directory node
I tried converting link1 to hard link but I can't do that either:
ln /path/to/my/linked/directory link1
ln: ‘/path/to/my/linked/directory’: hard link not allowed for directory
Any idea? How do you handle this kind of configuration? I just need to commit everything from /home/me/projects/project1 from a simple svn commit
If I understand your problem, you have:
project1/
project1/link1 -> ../../some/where/else
If you do a simple svn add link1 it adds a symlink entry to the subversion repository, but what you're trying to accomplish is getting the stuff under somewhere else into the tree.
If this is the case, then you're fighting in the wrong direction, you should make the real files and directories under link1, and make the target locations symlinks into the link1 directory. That would be a simple solution to the problem.
Another solution would be to make the location ../../some/where/else an svn location in it's own right, and make link1 an externals definition to that location. When you commit in the main directory, the externals would be committed at the same time which would achieve storing the information; however to ensure that the other location was kept in sync, you would have to make sure to update it to the same version as the stored data.
In my case, on my desktop, I have a settings directory:
$HOME/settings
This is a checked out copy of a directory containing .bashrc, .profile, .vimrc, .vim, etc. files and folders from an svn repo. All my profile files and directories were symlinks into this folder, so for example .profile -> settings/.profile, etc. When I make changes, they are reflected in the svn tree, which I can commit back to in order to ensure that I don't lose my config settings when I go to another system.
If you really want svn to follow symlinks as hardlinks (You can't make directory hardlinks because it would be a bad thing™), then you'll have to hack the svn client source so that it did what you wanted; but this would be a maintenance nightmare.
You could get away with making the symlink into a bind mount point directed at the target, but that has it's own issues - you would need to be root to accomplish this, and it ends up leaving funny entries in your /proc/mounts to accomplish this:
mount --bind /absolute/path/to/some/where/else project1/link1
Bind mounting does not work when mounting to inside the svn tree since the working copy format changes introduced by svn 1.7 - svn operations attempt to move files from .svn/tmp to the target folder, which would be a cross device link. The workaround in this case is to go from the inside out, i.e.:
mount --bind project/link1 /absolute/path/to/somewhere/else
With the change in the svn working copy format of a single .svn folder for the checked out tree, you will need to perform all subsequent operations from the true svn location, as it won’t work from the bind mounted folder, on the assumption that you have not mounted the entire checked out tree at that target location.
I am attempting to create a git repository to store all of my dotfiles and config files. My idea was to simply create hard links to all of the files I cared about and store those links in their own directory that I could turn into a repository.
I've hit a bit of a snag though with my ~/.gitconfig file. It seems that whenever I run the 'git config' command the link that I created no longer points to the right location e.g. the file in the repository no longer updates properly.
Here is an example using the shell and interactive ruby to determine the files linked state.
# Create the link
$ ln .gitconfig .conf_files/gitconfig # Create the link
# The files are in fact linked
[1] pry(main)> File.identical?('.gitconfig', '.conf_files/gitconfig')
=> true
# Update the gitconfig file by running a 'git config' command
$ git config --global alias.last 'log -1 HEAD'
# The files are no longer linked.
[2] pry(main)> File.identical?('.gitconfig', '.conf_files/gitconfig')
=> false
I assume this has something to do with the way that git is writing the .gitconfig file. Does anyone know why this would happen, or have any creative ideas for a workaround?
Try Eli Barzilay's solution in his comment at http://www.xxeo.com/archives/2010/02/16/dotfiles-in-git-finally-did-it.html:
So I’ve finally found a solution that takes the best of both: put the repo
in a subdirectory, and instead of symlinks, add a configuration option for
“core.worktree” to be your home directory. Now when you’re in your home
directory you’re not in a git repo (so the first problem is gone), and you
don’t need to deal with fragile symlinks as in the second case. You still
have the minor hassle of excluding paths that you don’t want versioned (eg,
the “*” in “.git/info/exclude” trick), but that’s not new.
This is completely normal, and is in fact the recommended way to overwrite config files. Git creates a temporary file, writes out the config, and then moves the new file over the old one. This way, you don't get an incomplete config file (data loss) if Git gets interrupted.
You can always write a script to copy or link your config files into your central repository.
Checkout this answer, perhaps it may be of help:
https://stackoverflow.com/a/3731139/1431696
In the meantime, have you considered doing the links in reverse? Create your repository full of config files, etc, and then in the place that you actually use your files, create a hard link to the 'real' file, which sits in the repository.
Thanks to Dietrich Epp's answer and advice I have decided to approach this problem from a different angle by creating the repository at the root of my filesystem, and using .gitignore to track only the files I am interested in.
My .gitignore file now looks like this:
/*
!/etc/
/etc/*
# etc files
!/etc/rc.conf
!/etc/asound.conf
!/etc/mercurial/
!/home/
!/home/matt/
/home/matt/*
# Home files
!/home/matt/.xinitrc
!/home/matt/.gitconfig
!/home/matt/.bashrc
# Vim files
!/home/matt/.vimrc
!/home/matt/.vim/
.netrwhist
In addition to not having to copy the files separately and keep them in two separate locations this has the benefit that should I need I can easily revert the changes without having to manually copy the files as well.
Thanks for the help guys!
I commonly work on multiple computers. I have various configuration files, eg, .bashrc, .gitconfig, .irbrc, .vimrc and configuration folders, eg, .vim/ that contain valuable customizations.
Sometimes I want small variations in configuration between the different computers.
I want to use version control to manage these different files.
do others use version control to manage their configuration files?
what are some hints that might make this easier?
what's the most elegant way of dealing with variations between the computers?
I'm comfortable with git; any other suggestions?
I keep a folder at ~/config/ which is a bzr repository. I push/pull the repository between my various computers to sync it up. I have an install script which I use to make symlinks to my home directory:
#! /bin/sh
# link all files to the home directory, asking about overwrites
cd `dirname $0`
SCRIPT_DIR=`pwd`
SCRIPT_NAME=`basename $0`
FILES=`bzr ls --versioned --non-recursive`
cd $HOME
for FILE in $FILES; do
ln --symbolic --interactive $SCRIPT_DIR/$FILE
done
rm $TARGET_DIR/$SCRIPT_NAME
If you want to use git instead of bzr, you can instead use:
FILES=`git ls-tree --name-only HEAD`
(I had to ask SO to figure that out)
EDIT: I don't actually do this anymore, now I have a dotfiles repo on github, with a nice rake install script that someone else wrote.
At the moment, I use a cloned git repo. To keep things simple, the only file that needs to vary between the different machines is .bashrc. It's nice if there can be just one version of this file that responds differently on different machines. Thus, in my .bashrc:
if [ $(hostname) == 'host1' ]; then
# things to do differently on host1.
elif [ $(hostname) == 'host2' ]; then
# things to do differently on host2.
fi
This obviously has some limitations (such as that a different technique would be required for .vimrc or other config files needing customization), but it works fairly well.
If you use git, you could define an "origin" repo to be the master; and then do a clone on each computer you work. you could use a branch for every computer to have your set of config files.
With CfEngine you can manage config files across machines and do also many more things!
The learning curve is maybe a bit high but worth it if you have to manage/update/maintain a pool of computers running linux regularly.
Easy. Use DropBox for that:
http://www.nixtutor.com/linux/sync-config-files-across-multiple-computers-with-dropbox/
I use slack for a similar situation. slack allows definition of roles/subroles so you can manage files with small variation either through a cloned file or patch. The slack directory is then managed by git in my deployment.
Here are some dotfile managers:
homesick: Based on Ruby
homeshick: Same as first one, but without ruby dependency
dfm: Written in Perl
git with branches for custom computers, with automated sync at login seems like a good solutions to me.
I've used etckeeper for versioning configurations, but I've never actually expanded to user configurations.
This kind of question comes up occasionally, and I've never seen a tool to handle this common use case, so I wrote a script that uses git and symlinks to manage these files.
See http://github.com/bstpierre/dotfiles
It is not perfect. There is currently a bug related to handling directories, and there is no support yet for variations across computers.
Before using any tool of this nature, make sure you have good backups!
I think what you want could be similar to what I've been doing...
Make a directory in home called .host_configs/ . This is version controlled. Or in my case it lives in a special folder on a central computer, I scp it down on any new machine. Inside it make a folder for every host that you want different configurations for. The folder for each host should be named after the short hostname for that machine. So in your git repo you have:
.host_configs/
homecomp1/
girlfriendcomp1/
workcomp1/
workcomp2/
In each host specific folder, put the .vimrc, .irbrc, etc., configuration files for that specific box.
And also, in each host folder make a file called .[SHORT_HOST]_rc. For instance, if your machine is name "sane" have a file named .sane_rc ... This file will contain the lines that would normally be in .bashrc that are unique to that host. For instance, if it's a mac and it needs alias ls='ls -GF' instead of alias ls='ls --color=auto' which works for most nix machines for ls with colors, put that line in the .[SHORT_HOST]_rc for that machine, along with whatever special functions, declarations, etc, that would normally go into the .bashrc or .profile etc. (or .zshrc, .tschrc, as the case may be). So the version controlled ~/.host_configs/ folder looks like:
.host_configs/
homecomp1/
.homecomp1_rc #special shell configs for this hostname
.vimrc #you know the rest
.irbrc
.Xresources
girlfriendcomp1/
.girlfriendcomp1_rc
.vimrc
.bubblebathrc
workcomp1/
.workcomp1_rc
.bashrc
.vimrc
workcomp2/
.workcomp2_rc
.bashrc
.vimrc
I use all the same barebones $HOME/.bashrc (or ~/.tshrc etc) on all of my machines. I just take the basic one that comes with the distro in question and move all of the host-specific configuration into the .host-configs/[SHORT_HOST]/.[SHORT_HOST]_rc file.
Put this at the bottom (of $HOME/.bashrc):
export SHORT_HOST="sane"
for file in `find ~/.host_configs/$SHORT_HOST -name ".*"`
do
ln -s $file `basename $file`
done
source ~/`.$SHORT_HOST`_rc
(Finds all of the dot-files for the host and makes a symlink in home to the~/.host_configs/foo_host folder).
Your dot files are in their normal location but they are symlinked to version control. The above also sources all of the lines in your [$SHORT_HOST]_rc file into .bashrc
You can commit back to git from the ~/.host_configs/ folder whenever you have changes.
That's what it looks like in shell, which is probably all you need, but if you need other features, I would write something that uses the same principles (sourcing an external .rc file into .bashrc and symlinking all the config files to the structured version control folder) in something more versatile/less ugly than shell. So instead of the above in your .bashrc, there could be:
export SHORT_HOST="sane"
ruby ~/import_conf.rb $SHORT_HOST
...and write your import_conf.rb to do more complex conf management, like placing a specific configuration file in some directory besides home, or handling a config folder like .ssh/, .subversion/ etc. That's what I do, it's pretty elegant for me, but there may be better solutions. Dropbox with some creative symlinks is also an excellent idea, though you're relying on a third party, and you need to be in a graphical environment. Also note there are inconsistencies between what you can do with symlinks + dropbox in Linux and shortcuts + dropbox in Windows if you implement something that wants to play with Windows.
Now there is also vcsh
From the README:
vcsh - manage config files in $HOME via fake bare git repositories
[...]
vcsh allows you to have several git repositories, all maintaining their working trees in $HOME without clobbering each other. That, in turn, means you can have one repository per config set (zsh, vim, ssh, etc), picking and choosing which configs you want to use on which machine.
Works perfectly, but may be a bit daunting if you are not an experienced git user.
Most of these answer address sync, but not how to tailor the files for the specific device. filetailor is an open-source Python program for this exact issue. Based on a YAML configuration file, it can make small changes to the files using device-specific variables or using device-specific comments in the files. Then, use another program such as Syncthing or Git to transfer the files.
For example, the following line would be commented out on every device except the one with hostname device1.
alias MYHOME='/home/dev1home/' #{filetailor device1}
Disclaimer: I had this same issue and made filetailor to solve it.
So, my situation is the following: I want to maintain my website using emacs-muse mode. For transferring the website (and version control), I want to use git. So I would create a hook in the remote (bare) repository that automatically copies the HTML subdir to the web directory. How can I do that from a hook? Also note that the whole directory contains a lot of files, so I can't export the whole directory.
Any help welcome.
You can use git archive, as it takes a path command. So, in your post-update hook you can do something like
git archive $SHA HTML | (cd dir/where/html/should/go && tar x)
this first creates a tarball of the subdir, and pipes that tarball to a tar command to untar it in the specified directory
(just a suggestion, as it may not be applicable in your exact configuration)
You might consider adopting this Web-Focused Git Workflow which, instead of copying, does push your repo directly on the web directory.
(From Joe MALLER)
Less complicated: Using Git to maintain your website (Daniel MIESSLER):
Daniel MIESSLER has an updated version of that same process:
Other suggestions are available at this SO question, like this post-update script mentioned in the Git FAQ.