I'm seriously about to stop coding and become a carpenter. This problem has had me stressed out for quite some time now and there doesn't seem to be any clear solution, other than forcing non-windows machines to use the file permissions windows seems to inflict.
Let's begin with the scenario. I have 2 development machines, one running Windows7, the other Mac OSX. They both are using Eclipse and EGit, and both have cloned the same project from a remote repo. That's where the similarities end, because my windows machine has a nasty habit of retaining a file mode of 644 (r-xr--r--) on its local repo, while the mode on the Mac defaults to a cool 775 (rwxrwxr--x).
So the problem's obviously the file permissions - GIT reports there are files that have changed due to differences in file modes and not actual content. The solution seemed obvious, run the following commands:
git config core.filemode false
git config --global core.filemode false
...which worked like a charm, except when committing and merging resolved conflicts.
For example, say files A, B and C exist on both the Windows and Mac repos. Next, let's change the file mode for these 3 files on the Mac machine so that the developer can edit them. Now change some of the contents in file A. Because we're ignoring the file modes (thanks to the commands above) only file A will be committed and pushed, ready for the Windows machine to fetch, merge and enjoy...
Now, let's edit file A again on the Mac and on the Windows machines, effectively causing a potential conflict, and let the Windows machine commit and push file A first. Then, when the Mac user commits their changes to file A and fetches the latest changes from the remote repo, a conflict is obviously created.
After resolving the conflict on the Mac machine and adding file A back to their local repo, committing that merge includes the previously ignored files B and C, and thus highlighting my problem! Why are the previously ignored files being included in this merge commit? This doesn't seem to be a Mac / Windows problem exclusively, as this problem can be recreated both ways...
This probably wouldn't matter if there were only 3 files, but this project I'm referring to includes thousands, and all these up and down push and pulls are insane. Am I missing something really obvious? Any help will be greatly appreciated!
So after a long and often frustrating run with trying to get Windows and Mac OS machines to like each other when comparing notes and changes over Git, it seems to just be the functionality of Git itself that's driven me mad, and a better understanding of how to better use Git seems to be the final answer.
Originally, I wanted to know how to continue ignoring file-mode changes (which Windows seemed to love updating with its own idea of what permissions and modes should be) while I was resolving conflicts created from updates to the files from someone else. Short answer: you can't. It's just the way Git works.
So how would you deal with this situation when it came up? Short answer again: use branching.
In my original way of using Git, I was continually working on my master branch on my local repo - bad idea already - so all my work would be committed there and all conflict resolution would need to be handled there too, forcing all files to be compared again and all permissions and file modes to come into question.
With branching, you work on another branch, commit to that branch, pull updates to your master branch, and merge you other branch with your master branch after that. Suddenly no more conflicts on the master from the remote repo, and you're winning!
Commands to do this (creating a branch from currently selected branch):
git branch newbranch
To checkout your new branch:
git checkout newbranch
To merge your new branch with your master branch (after you've committed to your newbranch, switch to the master first):
git checkout master
git merge newbranch
Hope this helps someone! -:)
well tbh, I'm not sure how you arrived at your conclusion since the obvious problem is git is not ignoring the file mode changes. This happens to us here too.
if you set that flag it seems to make no difference in some cases and still uses file modes to determine changed files.
that has to be a bug in git, what else could it be?
possibly your answer does not explain the rationale, therefore I dont think it's the correct answer, it's a workaround.
the correct answer is that git doesnt use filemode when it's told not to, it's obviously ignoring that and doing it anyway.
can you explain otherwise.
Related
I am having an odd issue with GIT.
I have a git repo for a small project I'm working on. There are no remotes, this is just for my own work. Up until a few days ago, my development didn't even warrant any branches.
I have finally needed to make a branch for some experimental code. When I was done, I simply checked-out the master branch to go back to where I was. And this is where problems started.
There are six files that change between the new branch and the master branch. Every time I switch / checkout either branch (switching between the two) most of those six file names change case.
For example, if the file was supposed to be someCode.py:
Sometimes the file name switches to somecode.py (Incorrect)
Sometimes the file name switches to someCode.py (Correct)
It doesn't matter which branch I pick, the result is different every time. And which files end up with which CaSe is different every time.
I suspected the GIT plugin for VSCode I was using (GIT Graph) at first, but it also happens with the included GIT GUI, and even happens if I use "git switch" from the command line.
I read about the core.ignorecase setting; it was set to True. I tried setting it to False and the problem persists.
Does anyone have any ideas what's going on?
Thank you
Details:
GIT 2.30.0.windows.2
Windows 10
Files are on a mapped network drive
File system is NTFS
Natively, Git is case sensitive so you could have two different files named filename.txt and FileName.txt. On some operating systems (e.g. Linux) that works fine, and on others (Windows) it does not. Note the same thing goes for branch names too; you can't have two different branches differing by case only on Windows. The reason for this is branch names are stored as a file on your drive.
Most likely your problem is that the files in question have different names on the two branches, but differ by case only. If so, pick which one you want (perhaps master), and on the other branch rename those files to match the casing exactly. If they are actually supposed to be different files, then change their name by more than just casing.
Another possibility is that two (or more) files with names differing by case only exist in the same branch, and switching branches simply causes the issue to come to light. Note it could be the files themselves, or it can be any of the directories in the path to those files could have different casing too. To determine whether this is the problem, navigate to the root of your repo in Git Bash and run this command:
git ls-tree -r HEAD | grep -i [filename-without-path]
If you see two or more files with the same name but different casing, you've identified the problem.
It seems I have resolved the issue - at least to a point.
I created a new branch, manually fixed the file names in Windows Explorer. Now, switching between master and the newBranch does things as expected.
However, if I ever switch to the firstBranch from the question, the issue resurfaces. There seems to be an issue with that branch, and switching in and out of that branch causes the issue.
I still do not have an answer as to why.
EDIT: OK, maybe not. Repo seems to be having this problem again with other branches.
I think I've done something rather stupid which may have cost me a couple of days of work. What follows is a question not so much about GIT itself as how to recover some files I have lost in the process of trying to use Git on a Mac.
I have been using Atlassian Sourcetree to make Git commits and pushes and to work with other members on a team. I have only been committing, pushing and pulling from Git.
As I've mentioned, I've been using SourceTree, but I wanted to evaluate Github for Mac as well.
At the time, I had made some changes to the files in my Git repo, representing about six hours of work. I did NOT commit or push these changes.
After I installed Github, I stupidly set Github to clone the repo to the same folder on my Mac as I had been making my changes in... essentially, Github downloaded the repo and overwrote all of my changes.
There were some files that were overwritten, and some new files that I created that were deleted.
Is there is a way to retrieve these files, either by some Git-based voodoo or some aspect of Mac OS X journaling that I'm not aware of? I would really appreciate hearing about it if there is.
So, from what I remember from having my life destroyed by my stupidity with git, it has a place where you can find your old code.
Go to your main repo folder and then type cd .git/lost-found/other/ or cd .git/lost-found/
You should be able to find a set of files that were older and you can then manually get them back by copying them in.
Here's some more links on it :
Recovering added file after doing git reset --hard HEAD^
Undo a git pull
http://www.quora.com/Git-revision-control/How-can-I-recover-a-file-I-deleted-in-my-local-repo-from-the-remote-repo-in-Git
So, I am working on a project with XCode. Happily, I found out that it keeps an Git repository within every project. So, after a mistake on a code, i just used
git checkout aux.c
to move back from theses mistakes. Unfortunately, as i just found out, Xcode does not auto-commit, so, I ended up with a blank file.
I didn't commited anything after this, but still can't figure out how to undo this checkout.
Sorry, you can't. :-( You're going to have to replace the file some other way.
There are two places where git tracks your files - commits, and the index/staging area. Since there was no commit, and you checked the version of the file out of the staging area, there's no other place it would be.
Do run git status just in case, to make sure it doesn't still show staged changes to that file.
Any chance you had it open in an editor still and could undo the changes to the file that git checkout made? Some editors like Textmate and SublimeText will allow that; others don't.
If the file has never been committed to the repository then unfortunately you are out of luck.
From the sounds of it, you simply have an empty git repository, which will mean your file has been lost and something Versions (which comes with Lion) or Time Machine may be your best bet at recovering from your mistake.
To confirm if anything has been committed to the repository, use git log. If you get an empty response then you're out of luck on the git front.
Unfortunately, this probably this isn't the answer you were looking for.
In fact, undoing a first commit on git is impossible. So, if you are running Xcode, commit manually frequently.
But, there is another way.
If you are running OS X 10.7 Lion or latter (not sure about Snow Leopard), you can try to use the versions feature from OS X to recover any file. Too late for me, but it should work
Best way to recover if your uncommitted changes would be to go to (Left Pane) Source Control Navigator -> Stashed Changes -> Look for a file which dated/timed earlier than your commit which you would like to reverse and click to apply stash changes to the file. That would bring back all the unsaved files back.
We are using a remote Git repository located on a Linux server at the office. All clients are Windows PCs with Git Extensions installed as a client (running with msysgit).
On a client system, if I try to do the following:
git branch Branch1
git branch branch1
the second command is going to fail, telling me that a branch with that name already exists. That is what I expect, since I set the core.ignorecase to true in git config.
But, if I log onto the Linux system directly and run the same commands, both branches will get created, even if the core.ignorecase flag is set to true.
I would have expected the second command to fail too, since I configured the repository to ignore the case, but either the flag does nothing on Linux systems, or I missed something.
Can anyone help me understand the issue as we plan on migrating our SCM from Source Safe to Git shortly and this issue is scaring us. What would happen if two developers create branches with the same name, but different case, and push the result on the Linux repository?
I would like to add more details over #meagar's answer:
FAT32 / NTFS are case-preserving file systems. That is, if you name a file "Foo.txt", it will be stored as ""Foo.txt". If you save a file as "foo.txt", it will be saved as "foo.txt". But since it is case-insensitive, "Foo.txt" and "foo.txt" are effectively the same and you cannot have both files in the same directory.
In your repository in Windows, if you change the name from "Foo.txt" to "foo.txt", and if you do not git to show that as a change , you can set core.ignorecase configuration to true and git will not see that as a change. If you set it to false it will. ( But because of the nature of the filesystem and git, it will seem like a new file foo.txt was added, adding to confusion on Windows).
That's the purpose of the core.ignorecase
Coming to the branch. Branches are just pointers to a commit. These pointers are just files. These files are stored in .git/refs/heads. When you create a branch, say, bar, a file named .git/refs/head/bar is created. Now, in Linux, when you create a branch named Bar, it can go ahead and create a file .git/refs/head/Bar and hence allows the branch creation. But on Windows, you cannot create .git/refs/head/Bar and hence you will not be able to create the Bar branch when bar exists. Realize that core.ignorecase is to do with files in your repository - your code base - and has no influence over the metadata files of git.
So you will have to live with and adjust to the fact that in Linux, you can create branches with same names, differing in case, but in Windows, you cannot.
How to make “git branch” respect the “core.ignorecase” flag on Linux?
You can't, because the flag doesn't do what you think it does.
core.ignorecase
If true, this option enables various workarounds to enable git to work better on filesystems that are not case sensitive, like FAT.
core.ignorecase has nothing to do with the behaviour you're describing, it is unrelated to the case-sensitivity of branch names. Git being unable to tell the difference between Branch1 and branch1 on Windows isn't related to whether core.ignorecase is set, it would behave the same way regardless.
... but either the flag does nothing on Linux systems, or I missed something.
You didn't miss anything. The flag does nothing on Linux systems. core.ignorecase isn't for making operating systems case-insensitive, it's for allowing Git to work on broken case-insensitive operating systems. Linux is fundamentally case-sensitive, and so is Git. You should be trying to work with this, and mandating that your developers use lower-case for their branch names. You should not be trying to make Git emulate broken behaviour from other operating systems.
What would happen if two developers create branches with the same name, but different case, and push the result on the Linux repository?
Then you would have two completely different branches, one in lower-case and one which was wrongly named, and somebody would be forced to merge and discard their wrong branch. This is something you'll be doing routinely anyways, as a side-effect of using Git.
I'm doing a single developer Visual Studio solution and reached a point where I'd like to incorporate Versioning Control. Several posts address this issue, but one problem I'm facing is a large merge. I have a production copy of the solution and a beta copy. They are NOT dramatically different, but they will require a number of interactions I suspect. I'm using TortoiseSVN and have imported the production version.
Yes, I know I should have used Version Control from the start, but that is hind sight. Would it be best practice to simply use the beta as a reference and work the interations from scratch. Or should I branch off and import the beta separately, then attempt to merge the change. Or is there another alternative I'm missing.
Thanks,
dgp
well, I have experienced SVN in the past ... and I must say, it's lovely cause it's really easy to understand the concept, but it's awful terrible when things pass from the plain commit.
I'm currently using GIT (to host small code on GitHub) and Mercurial (Hg) (I use Kiln in the company - was recommended by myself so they can start using - and in BitBucket for personal use)
I have used SVN for more than a hole year and every time I need something from "the past" or to merge something, it was a nightmare, but the server/client concept was really a break deal and extremely easy to get it... but I found my self, over and over to do merging by hand :(
When GIT started to be hot, I was afraid to move as, dang! SVN was a pain, why should be different in a DVCS?
This videos rocked my world, [ part 1 part 2 ], only then I understood DVCS vs VCS and it was with this that I moved COMPLETELY to DVCS and never go back... proudly!
For your problem, I would install git (or hg), and then create a repository on the folder you have your current source with:
git init will tell your folder, "Hey, I'm a GIT Repo"
git add . let's add all files and folders to be tracked by git
git commit -m "initial commit" let's save all the hard work :)
So, now you have a tracked code, you can simple create a branch and overwrite all your files. YES, worry not, you don't need to have copies of your code in a folder called branch ;) no more copies! all is in the GIT database
then, after creating the branch, changed the files, added all files to be tracked on that branch and committed, safely do a merge :)
ohh, and you don't need a server connection to do all this, all you need is a computer with GIT installed... no more connection dependencies! DVCS is cool or what?! :D