Safely using junction or mklink /j with a git repository on Windows - windows

Using Git on Windows, I'm trying to deal with content that's external to my git repo. We have artwork and content files for instance that are being updated by non git-users in google drive so to capture these changes I've setup something similar to the following;
d:\MyRepo
\.git
\code1
\images1
\fonts (junction) => c:\users\%username%\google drive\designerLtd\fonts
\etc
Where 'fonts' is a folder has been linked using either junction.exe or mklink /j (same thing). This generally works out great because Git status immediately highlights new changes (either on purpose or by accident) and prepares them for checkin or undo.
ISSUE: sometimes when switching branches Git prunes the linked directories and re-creates them if content in those folders is different between branches. In effect it breaks the link. Now Git is always correct and the build is consistent but it's not always obvious that it is no longer keeping track of those external resources.
Worse still, it can delete files in the external location. They can be recovered from git of course, but it's very unwieldy.
Swapping the content in the external locations when branches are switched isn't a problem, because there's only one PC that's hooked up this way and they're easily merged, but I just wish it didn't break the links.
QUESTION: Is there a better way to allow external junction points within a Git repo on Windows?
To be clear, there are no symlinks in the GIT repository (yet) as far as I know and this isn't a question about interoperability between Unix and Windows git clients (which most of the other questions on SO seem to relate to).

You can modify permissions of the junction point so that git can no longer delete it. Git usually doesn't care if removing a directory fails (except if it needs to replace the directory with a file).
See "Usage Recommendations" in https://support.microsoft.com/en-us/kb/205524

Related

Checked out a repo from remote but when I do a git status a file shows up as modified — how to fix?

I am using Windows and Git and I had modified a file. No matter how many times I did a git add and commit, the file kept showing up as modified and i could not for example do a git pull --rebase. I assume I did something wrong and screwed up the local Git repo so I decided to clone the repo from github, into a completely new directory. To my surprise, even in this new directory tree when I do a git status the same file shows up as modified -- it is as if it is somehow modified in the github (remote) repo which does not make sense to me. Moreover, the version of the file in cloned local repo does not have the latest version of the code that i can see when i look at the code on github. How can i fix this? I am concerned that someone else cloning the code will end up with the same problem. (Apparently only I am seeing this problem -- I did not somehow manage to corrupt the github repo which leads me to believe this is a git/windows issue.) As far as what I think I did wrong is when I modified a file and did a git add, i misspelled the directory path by using a lower case letter instead of an uppercase and then adding one file resulted in the other, properly spelled path showing up as modified and vice versa. I don't know if a symlink on windows got created -- the file contents are identical. But one would think cloning (via Eclipse) into a completely new directory tree would make this a non-issue.
I looked through replies but it seems like the basic problem is Window's case insensitivity and this caused some (to me) weird behavior. In particular, I simply could not delete one of the folders -- they were "entangled." So the simple solution was to delete the folder and its contents from unix which is case sensitive. Then I checked out a fresh repo and problems appear to be completely resolved.
You mentioned in a comment that you discovered one commit containing two problematic files: one named Login/Login.tsx and one named login/Login.tsx. This comment is on a related question; see my answer there for a discussion of Git's method of naming files in its index, vs what your OS requires in your working tree.
Your solution—use a Unix or Linux machine, where you get a case-sensitive file system, to repair the situation—is probably the easiest and best way to deal with this. If you can establish a case-sensitive file system on your own machine, that also allows easy dealing with this (see my answer to another related question for a macOS-specific way to make a case-sensitive file system).
Given that what you wanted was simply to delete one of the spellings, though, git rm should allow you do that. In particular git rm --cached login/Login.tsx would drop login/Login.tsx from Git's index, without affecting Login/Login.tsx. This could leave your working tree with an existing login folder, though.
It's important—at all times, really, but especially when working within a situation like this—to realize that Git itself doesn't actually need or use your working tree to make new commits. Each commit contains a full snapshot of every file that Git knows about. These files exist as "copies" in Git's index.1 Hence there are actually three copies of each file:
A frozen version of each file appears in the current commit (whatever that commit's hash ID is).
A "copy" (see footnote 1) of that version appears in Git's index. You can replace this copy with different content, and the read-only copy in the commit doesn't change. You can remove this copy entirely, and the read-only copy still doesn't change. Nothing in any existing commit can or will ever change. The index copy exists precisely so that you can replace it, or remove it, or whatever. In effect, the index—or staging area, if you prefer this term—acts as your proposed next commit. It's merely filled in from a commit.
Finally, there's a regular, ordinary, everyday file. This copy goes into your working tree or work-tree. To put this copy in place, Git must use your OS's file-manipulation facilities. That may require creating folders and files within the folders. If those are case-insensitive, and Git goes to create a Login folder when a login folder exists, or vice versa, the OS will say: nope, sorry, already exists. Git will do its best to accommodate the OS by using the "wrong" case anyway, and will create a file within that wrong-case folder—or perhaps destroy some other work-tree file that has the same name except for case, or whatever.
This last bit, where your work-tree files end up with the wrong names and/or in the wrong folders and/or end up overwriting similar files whose name differs in case somewhere, is a problem for you. It's not a problem for Git, though. Git just keeps using the index copies of each file. The next git commit you run uses whatever is in Git's index. The fact that your work-tree doesn't match is not a problem for Git. It's just a problem for you, because the normal everyday git add command means make the Git index entry for this file match the copy that's in my work-tree, and if that's the wrong copy, well, that's a problem.
In any case, once you have a correct commit in Git as your current commit, and extracted into Git's index, you can do whatever you like to your work-tree, including remove large swaths of it, or rename folders, or whatever. Get it set up however you like, then use git checkout or git restore to re-extract all or part of the current commit to your work-tree. Now that you've eliminated the name-case-issues in Git's commit and index, and cleaned up or removed any problematic files and/or folders in your work-tree, Git can create correct-case folders and/or files as needed. It's the process of getting the correct commit into Git that's painful, except on a case-sensitive file system.
1"Copies" is in quotes here because the files in Git's index—which Git also calls the staging area—are in a special Git-only format that de-duplicates content. When the copies that are in Git's index match the copies that are in some existing commit, Git is really just re-using the existing commit's files. Files with all-new content actually require a new internal blob object, which Git creates as needed; after that, the content will be de-duplicated as usual.

How do I stop OneDrive from downloading git.exe on Windows?

I have used Git on Windows for a while, but recently changed the setting and got this.
On almost every command for Git Bash (also on PowerShell and Github Desktop) I get
git.exe is being downloaded on OneDrive
(translation may not be exactly the same)
The setting that changed recently is moving my repos to a OneDrive folder in order to have them synced between two sessions: that is work desktop and remote virtual machine.
I can see that this may not be ideal, but it really works for me since I have the same settings on both sessions, and not really get used to doing many commit-push-pull. Not the main topic here, but feel free to comment.
(Edit): Upon reading solution, there are other ways to set this syncing that doesn't mess up with the internals of Git. Look for that instead. Thanks.
In any case, the strange thing is that the notifications happen only on the Remote Virtual Machine, but not on the desktop.
I have seen some notifications about some files in the repos, which I then attribute to OneDrive being nosy about every move I make file I move. But then I've also seen files I don't know about, and theres always git.exe attached to the notification.
In the first scenario I have tried tuning down the notifications for OneDrive. Some might say Microsoft does have a background for not letting users setup their notifications, so I'm still looking.
Thanks.
Most file syncing tools like OneDrive and Dropbox operate by syncing data file by file. This is a great approach if you're working on a single word-processing document or spreadsheet. However, it's not as great when you're working with a Git repository.
When changing between branches or making a commit, Git changes and creates a lot of files all at once. In order to be synced correctly, all of the created files must be written in a similar order: all the blobs must be written, then the trees, then the commits, and then the refs can be updated. If you do this out of order, your repository can be corrupted, since you can have branches that refer to objects that don't exist (or objects that refer to other objects that don't exist).
In addition, these tools can end up deleting files you wanted to have in your working tree or recreating files you didn't. So overall, you don't want to sync any Git repository using one of these tools.
You can write a bundle file with git bundle and sync that, or you can use rsync to sync a repository provided it's idle (not being modified) when you do. Note that if you sync a working tree, Git will need to refresh all files when you sync it across to the new machine, and also Git doesn't try to defend against untrusted users who have access to the working tree.
It's also not a good idea to sync your Git installation itself via OneDrive, which is what it sounds like might be happening. Instead, install Git for Windows on each machine independently and don't try to sync it across. OneDrive should have configuration options that let you control what's synced.

How to restore files git deleted during clone

After working on something for a while, I thought I should put it in a git repo. Using gitlab, I created a new repo and cloned it from the command line onto my Windows 7 machine. This created a folder with a .git folder in it. I then copied all the files I'd been working on into the folder. I then noticed that the command line where I had cloned the repo was asking for a password. I entered the wrong password a couple of times and stupidly hit ctrl+c. Next thing I knew, the folder with all my files was gone. It is not in the recycle bin. Is there any way to restore these files?
Unfortunately, they are lost and git won't help you here. You should rely on file recovery tools to help you recover the files (long, hard and boring process) if you can afford to rewrite your code from scratch.
Buy I could tell you what you did wrong with git and what you should have done to never have been in such a situation...
You should have done :
1. Create a local repository in your project directory with 'git init'.
2. Do as much development and commits as you want (but at least one...). You are now protected against file deletion!
3. Once you think it worth to be shared, like you do, create the repository in gitlab.
4. Add the gitlab repository as a remote in your local repository.
5. Push the history to the gitlab central repository.
Like that, you should have avoided all the risky action you did and your work is secured at all times.
Standard methods for removed file restoration apply:
Suspend any user operations on the HD (don't create/copy/remove files). This will increase your chances when trying to restore.
Check if you have the file copies/originals in other folders. You mentioned that you had copied them previously into git folder. May you have them in the original directory?
Do you have any backup system running (like Crashplan, etc) ? Check if you have a backup of the files
If nothing of the previous helped proceed to the undelete operation - use dedicated utilities like this one for ex.: http://www.ntfsundelete.com

SVN - Steps to get all the files from a repository?

We have an existing repository on the network accessed via HTTP:.
Should I first import these files to my local machine? I tried importing directories, files, etc., everything is empty in my local folders. It says "success", but nothing ever shows up!
It doesn't make sense to create a repository on my side. But all the tutorials seem to say that, but then I think they're assuming you're starting from nothing.
My experience with Tortoise SVN has mostly been negative. Typically whatever I think I should do turns out to be incorrect, and I end up having to undo, and redo, or lose my work. Once I even managed to corrupt the main repository and it had to be restored from backup.
I absolutely cannot damage this existing repository!
If you're used to CVS or some older version control systems, note that SVN uses the same terms differently. In those, checkout often means lock in exclusive mode.
In SVN checkout will make a copy and automatically manage the revisions and help you merge from multiple sources. You don't need to lock a file, unless it's graphical or some other binary where merging doesn't make sense.
So in TortoiseSVN, you can checkout, and edit the files. The icons on the files will change to indicate their status.
SVN is easy in comparison to git, where the same terms are again redefined and significantly augmented!

Make a working copy from part of an existing working copy in SVN

I have a working copy of a SVN repository. C:\myrepo on my computer points to https://example.com/svn. It has a subfolder in it, /foo/bar. This folder is really big and it's a remote repository, so checking it out again would take a very long time. I'd like to give my colleague a working copy of just /foo/bar, not the whole repository (because the whole repository is even bigger and contains a bunch of stuff that will confuse them).
I can make a copy of my working copy, C:\myrepo-bar and then use svn switch https://example.com/svn/foo/bar but it says there's no common ancestry (which is true) and so (if I force it) it checks out the whole folder again.
Is there any way to get around this and get a working copy of just https://example.com/svn/foo/bar given that I have a working copy of https://example.com/svn already? I'm using tortoiseSVN but I'm comfortable enough using SVN on the command line.
That depends. In general: no. SVN working copies are not like Git or Mercurial repositories; they do not contain any history or other information that is contained in the repository, only a copy of the selected version of the files.
If, however, you are using an old version of the SVN client, a version old enough to put a ".svn" directory in every subdirectory of your project, then you may be able to just copy the subdirectory (including the .svn directory inside). I'm not sure if this will have consequences with username or whatever, I only ever did that for my own use. And, recent versions of the client have removed the .svn directory from all but the working-copy root, so this is not an option for recent clients.

Resources