Handle existing files when cloning
RichiH opened this issue ยท 12 comments
User expectation seems to be that existing files are left intact when cloning a repo.
This is counter-intuitive to me, but with a proper warning, it's not an issue so why not?
- Fetch
- Detect files
- Move existing to tempfile
- Finish clone
- Move tempfile to existing
Are you proposing to do this by default or via an option? If default then we will need an option to do the opposite as well.
What I'd like:
- Fetch
- If file(s) already exists {
- display conflicting file(s)
- ask user to cancel, overwrite or create a backup
- cancel -> exit
- overwrite -> rm file
- backup -> (mv file file.backup) }
- Finish clone
Alternatively, keeping the default behavior but introducing a new flag e.g. vcsh clone repo --overwrite
would be almost as good.
I can't see why one would like to finish with Move tempfile to existing, because that would overwrite the dotfile you just cloned.
As I said before in #190, maybe I am misinterpreting the full vcsh/mr concept...
Or vcsh clone [--backup|--overwrite] $url $repo, which could overwrite the files or back them up to ~/.config/vcsh/repos.d/$repo.git/bakcups
What is verdict on this issue ? It would be really helpful for bootstrapping a new environment
As a former yadm user I really like the idea of using git stash to handle conflicts with existing files. This way, cloning always succeeds and you can easily review / merge any differences between the local version and the cloned version of a file with the full power of git. This might be integrated to the core functionality of vcsh, but it can also be achieved with a pre-merge hook:
#!/bin/bash
# vim: set ft=sh:
REMOTE_BRANCH=$(git branch -a)
# unfortunately VCSH_BRANCH is not exported by vcsh
VCSH_BRANCH=${REMOTE_BRANCH#*remotes/origin/}
git reset --mixed origin/${VCSH_BRANCH}
git stash && git ls-tree -r --name-only origin/${VCSH_BRANCH} | xargs rm
rm ${GIT_DIR}/index ${GIT_DIR}/refs/heads/${VCSH_BRANCH}
Be careful, it seems to work but is not tested very well. It will delete your pre-existing files after they have been stashed. After vcsh clone you can show the differences:
vcsh reponame stash show -p
You can restore the local files with
vcsh reponame stash pop
I honestly can't believe this is still low priority after all these years! When I set up my repositories with vcsh, I thought cloning my dotfiles into a new system would be as simple as running vcsh $repo clone ...
, since newly created users will most likely always have simple .bashrc
and .profile
which were copied from /etc/skel/. [--backup|--overwrite] is really essential.
@teresaejunior I agree this should have been dealt with years ago. In the mean time you might review my solution using hooks that handles exactly this situation. The tricky thing with setting up a new system is that you need these hooks in place before cloning anything, and the hooks themselves are in my repos. To deal with the catch 22, I use a bootstrap script that downloads the hooks before cloning any vcsh repos. It also takes care of getting SSH keys in place to clone other vcsh repositories, but that is out of scope for this issue report.
Thanks, @alerque! Since I don't need multiple repositories, I've moved at least temporarily to yadm.
I too am using a hook-based solution but unlike @alerque I move the existing files to a backup directory and leave them there; my common use case is to replace existing files with the ones I track with vcsh.
Anyway, however this is handled, It would be good to have VCSH_BRANCH
available in the hooks called by the clone
command, as @PiQuer remarked.
@ao2 mind sharing that hook with me?
@ao2 mind sharing that hook with me?
@soulofmischief I have something like this in hooks-available/backup-existing-files.sh
:
#!/bin/sh
set -e
BACKUP_DIR="vcsh-backup/${VCSH_REPO_NAME}-$(date "+%F-%R")"
git ls-tree --name-only origin/master | \
while read -r object;
do
if [ -e "$object" ];
then
echo "The path '${object}' already exists, moving the existing copy to '${BACKUP_DIR}'."
[ -d "$BACKUP_DIR" ] || mkdir -p "$BACKUP_DIR"
mv "$object" "$BACKUP_DIR"
fi
done
unset BACKUP_DIR
And I link it to hooks-enabled/pre-merge.00-backup-existing-files.sh
.
It's still rough so I didn't commit to my public repo.
For the record, this is the hook I implemented to move the clobbering file out of the way by simply renaming the file in place: https://gitlab.com/brlin/brlin-os-customizations/-/blob/6dfc7742/files/vcsh-hooks/pre-merge-10-unclobber.sh