How to automatically download files from github without copying the repository - bash

I have a number of scripts that I use almost everyday in my work. I develop and maintain these on my personal laptop. I have a local git repository where I track the changes, and I have a repository on github to which I push my changes.
I do a lot of my work on a remote supercomputer, and I use my scripts there a lot. I would like to keep my remote /home/bin updated with my maintained scripts, but without cluttering the system with my repository.
My current solution does not feel ideal. I have added the following code belowto my .bashrc. Whenever I log in, my repository will be deleted, and I then clone my project from github. Then I copy the script files I want to my bin, and make them executable.
This sort of works, but it does not feel like an elegant solution. I would like to simply download the script files directly, without bothering with the git repository. I never edit my script files from the remote computer anyway, so I just want to get the files from github.
I was thinking that perhaps wget could work, but it did not feel very robust to include the urls to the raw file page at github; if I rename the file I suppose I have to update the code as well. At least my current solution is robust (as long as the github link does not change).
Code in my .bashrc:
REPDIR=mydir
if [ -d $REPDIR ]; then
rm -rf $REPDIR
echo "Old repository removed."
fi
cd $HOME
git clone https://github.com/user/myproject
cp $REPDIR/*.py $REPDIR/*.sh /home/user/bin/
chmod +x /home/user/bin/*
Based on Kent's solution, I have defined a function that updates my scripts. To avoid any issues with symlinks, I just unlink everything and relink. that might just be my paranoia, though....
function updatescripts() {
DIR=/home/user/scripts
CURR_DIR=$PWD
cd $DIR
git pull origin master
cd $CURR_DIR
for file in $DIR/*.py $DIR/*.sh; do
if [ -L $HOME/bin/$(basename $file) ]; then
unlink $HOME/bin/$(basename $file)
fi
ln -s $file $HOME/bin/$(basename $file)
done
}

on that remote machine, don't do rm then clone, keep the repository somewhere, just do pull. Since you said you will not change the files on that machine, there won't be conflicts.
For the scripts files. Don't do cp, instead, create symbolic links (ln -s) to your target directory.

Related

How to zip and ignore all files specified by .gitignore

I have a few dozen git repositories under one directory, all of them contain not only source code but also build artifact, developer artifact, blobs and other data normally ignored by .gitignore
I would like to quickly transfer these source code to another computer. Is there an easy way to package everything that is not ignored by git?
To add more context:
I have 50-ish git folders or so, each on different branches with some current changes
I would like to copy all files that are tracked by git, at the current state ( current branch plus current local change )
If by cloning them all, it means to go to each folder, commit the current changes locally, remember the branch name, git clone local branch to another folder, do that 50 times then I am strongly agaist it
One-liner:
$ alias gitzip="git archive HEAD -o ${PWD##*/}.zip"
$ cd mydir
$ gitzip
If you want to include history, use git bundle (or xeyownt/git-subundle if your repositories have submodules)
See this script as an example:
for repository in ${repositories[#]}
do
echo "$repository..."
declare file_name="../$repository-$(git rev-parse --short HEAD).bundle"
cd $repository
if [ -f $file_name ]; then
echo 'Found bundle is current'
else
git bundle create $file_name --all
fi
cd -
done
Each repository gives one file (without anyprivate or ignored files), that you can easily copy and, once copied, cloned from.
You can try this :
for dir in repo1 repo2 repo3; do
git -C "$dir" ls-files | perl -pe "s[^][$dir/]"
done | zip /tmp/test.zip -#

How to replace folder with symlink on a server

We have a git repository for a scientific software where we need to maintain a certain folder structure for our data files.
These folders should remain empty, everything that will be put there should not be tracked by git. However, it is necessary that those folders exist.
The solution to accomplish this was to add a .gitignore file into every directory which looks like this:
*
!.gitignore
which means everything inside this folder is ignored except for the .gitignore file.
This works very well.
We maintain all our data on one particular server.
Our scientists use this server often for their calculations.
It would be very convenient to be able to replace the data folders from the git repository which currently contain only the .gitignore file with a symbolic link to the full data files on this server. The data files on the server also have a .gitignore file which looks exactly the same as in every repository.
I wrote a bash script to do this which looks like this:
rm -r path/to/empty/data/in/repository/name
ln -sfn /absolute/path/to/data/on/server/ path/to/empty/data/in/repository
Now the software runs perfectly and you have access to all the data without copying it into your git repository.
However, git now gets confused.
If I run git status only my changes are listed as expected. It does not complain about the new symbolic links which replaced the existing directories.
As soon as I run git add . to stage my changes the symbolic links appear as new file: and the .gitignore files in the replaced folder are listed as deleted:.
This seems like a problem to me because as soon as somebody pushes his code changes that he made on the server the symbolic links would get uploaded (I guess) and the .gitignore files would get removed and thus the folder structure would not remain.
Is it possible to tell git that it should compare the content of the symbolic linked folders rather than the symbolic link itself?
PS: I know this seems like a software design issue with the static folder structure which is inside git but I do not want to discuss this here. We are all scientists and no programmers and the software is now developed for over 10 years by many different people. It is not possible to change the code to make it more flexible.
EDIT: This bash code reproduces the problem:
cd ~ #setup
mkdir tmp
cd tmp
mkdir server #server data folder (this one is full of data)
mkdir server/data
printf '*\n!.gitignore' > server/data/.gitignore
printf 'data file 1' > server/data/data1.txt
printf 'data file 2' > server/data/data2.txt
mkdir repo #repo data folder (this one only contains .gitignore file)
mkdir repo/data
printf '*\n!.gitignore' > repo/data/.gitignore
cd repo # create a dummy repo
git init
git add .
git commit -am"commit 1"
git status
cd .. # replace data folder with server/data folder which hase exactly the same content
rm -r repo/data/
ln -sfn ~/tmp/server/data/ ./repo/
cd repo
git status
At the end git status should ideally not list any changes in the repository.
EDIT:
I found a workaround: instead of linking the whole directory I'm now linking the content of the directory:
ln -sfn /absolute/path/to/data/on/server/* path/to/empty/data/in/repository/
this works because the symbolic links are irgnored due to the .gitignore file.
Drawback is that it only works with existing data. As soon as there is a new file in the server directory I have to run the bash script again.
Git tracks symbolic links. What you're trying to achieve can be done with bind mounts.
Replace the final ln -sfn ~/tmp/server/data/ ./repo/ with sudo mount --bind $PWD/repo
$HOME/tmp/server/data/

Touch all files in a git repo so git thinks they are changes

I need 'touch' (I think) all files in my git repo (lots of files) so that running git status will have them as modified (and then I can add and commit them). I need to do this because our in-house tool uses the files from a git commit to generate a report ... which I've been asked to do
In posix environments I think I could just touch a directory and go from there.
I don't think that's possible because git detect that a file change if the content of the file changed. Touching the file will have no effect (even on unix).
Perhaps changing the permission on the file could be a very dirty solution but I'm not even sure of that and that's if you find a new permission that don't introduced some bad side effects!
The better solution is to update your reporting tool.
And being obliged to commit changes for ALL files to trick your tool and dirty your history is in my opinion a very bad idea...
If you were asked to "generate a report with all files" does that mean list all files in a commit? Cause that's easily done with something like a git ls-tree -R HEAD
I had a demo repo that had a bunch of files in it, that had commit messages that I didnt want showing up in the demo - and to be clear, the repo was "garbage", in that it was just basically a dump of files to demonstrate a folder structure.
That having been said, one way you could do this is to
create a new temporary folder in your repo, for example "ez"
move all the files of the repo into it, e.e. "$ mv * ez"
commit that locally, the do the reverse and move them out again
"$ mv ez/* .; rmdir ez"
That would show all files as having been changed. For my purposes, I then committed that change too, and pushed it up to my demo repo.

Untrack all files on git

In the move from C9 to hosting on my Macbook via SSH, I've had to re-download Kohana and change some other things just to get my site working; I don't want those to be committed. Is there any way to untrack all tracked files so only future changes are committed? Or is there something else I should be doing?
I'm on a Macbook running Mountain Lion with Apache and PHP turned on.
Even simpler:
cd /root/directory/of/your/local/repo
git rm --cached -r .
^^^
(space - dot)
Even even simpler:
git clone url/for/Kohana /different/local/path
git rm --cached File
Will delete the file in the index, so it will no longer be tracked, but won’t physically delete it. This will untrack the file only for current branch
[OR]
Use this git command. After you do this, git stops checking the file for possible modifications.
git update-index --assume-unchanged <filename>
At any time, you can track again by setting --no-assume-unchaged flag
git update-index --no-assume-unchanged <filename>
But these command do not affect the remote repository.
I'm not exactly sure what you mean by "untrack all tracked files so only future changes are committed". As you need to track files so they can be committed.
If all you just want to do is not track Kohana and the other downloads, then just remove them from your working directory using git rm --cached <file> or even better create a .gitignore file.
There are many helpful posts on stackoverflow to assist you with creating a .gitignore file for your project. By using this, you can exclude an entire folder easily.
For Mac, it would also be helpful if you could see hidden file as the . file is hidden. This page shows you how to see hidden files on Mountain Loin - http://www.mikesel.info/show-hidden-files-mac-os-x-10-7-lion/

one-way symbolic link from repository to build directory

I am writing code inside of an svn repository but I really don't want to test run my code from within the repo. (I have a ../computations directory outside of the repo for this). Ideally, the computations directory would be a one-way symbolic link from the repo so that each edit to the source (inside the repo) will be immediately available to the ../computations directory.
The problem is that there is no such thing as a one-way symbolic link. An rsync shell script is about as close as I can get to a one-way mirror of the repo, but I am trying to minimize the chances of me forgetting to (or becoming tired of) 'updating' the ../computations directory.
What are my options here?
More details: I am working with C++ and Python code that spans more than one - but less than ten - directories, and editing in vim.
Alright, here goes:
We have an rsync script named snk in /usr/local/bin that looks like:
#! /bin/bash
# this script will rsync -a the ../repo directory
# with the ../computations directory on various architectures.
# leave this script here (in the repo!) and create a symlink to it from someplace in your $PATH
# get this host
HOST=${HOSTNAME}
# define various hosts in order to dictate specific rsync commands
hostA="someHost"
hostB="someOtherHost"
if [ "$HOST" = "$hostA" ]
then
rsync -zvai --exclude=.svn /full/path/to/repo/on/hostA/ /full/path/to/computations
elif [ "$HOST" = "$hostB" ]
then
rsync -zvai --exclude=.svn /full/path/to/repo/on/hostB/ /full/path/to/computations
fi
Then we went to the Google and found: this qeustion about 'vim: rsync on save' and gave it a shot. Take a look at this portion of my new .vimrc file:
:if system('pwd') =~ "/full/path/to/base/of/repo"
: au BufWritePost * !snk
:endif
This is a first-order approximation to a solution to my problem, I hope it helps!
Thank you vipraptor!

Resources