Github version of Perforce's explicit check-out feature - github

I've recently moved to Github (VS2017's built-in support) from Perforce for some individual projects. There is a feature in Perforce called "make writable" that allowed you to write to a file locally and then only submit it to the server by explicitly checking it out then submitting it.
This was used extensively for any binary files (.exe, etc) that only needed to be pushed very rarely but still needed to be written to.
Unfortunately from my limited experience with Github, it seems that all files are set to writable and are always marked as "changed", even exes. Is there a setting I can make or setup that allows Github to only mark a file as changed explicitly so I can't accidentally push an incomplete, broken, or debug .exe?

Updated answer: So, I forgot, if the file's tracked by Git at any point, then it gets a bit ugly. There are ways around this, but it isn't a single command to do this.
IF you want to do the .gitignore route, you can. But there's an added step (see below for first step). You have to, after each commit you do of the .exe file, run git rm --cached <filename>. This will remove the metadata around the file telling Git to track it. Once you do that, it won't show up anymore in the Changes list in the Visual Studio plugin (if you're on commandline it won't show up in git status). Then to add a file, you do what I mentioned below, which is to do the git add -f <filename>.
If instead, another way to do this, would be to run git update-index --assume-unchanged <filename>. This tells Git to ignore changes to the file. When you want to commit it, first run git update-index --no-assume-unchange <filename> and do your normal git add git commit workflow, then once you've committed it, run again the git update-index --assume-unchanged <filename> bit. It's messy, and honestly, I'd write a custom tool in VS to do this rather than relying on the built-in SCM tool in Visual Studio.
Original answer: Best way to do this (IMO, others will have their own opinion) is to add the files to your .gitignore. Then if/when you really want to commit them, do a git add -f <file> and then commit as normal.
Edit: Note that this is something everyone will have to do to avoid accidentally committing. A way around that is to commit your .gitignore as well so everyone has the same behavior.

Related

Importing existing files in repo to new LFS storage (using SourceTree and Git LFS)

TL;DR: What is the least intrusive way of migrating existing files to the LFS storage, once LFS has been initialized on the repository, and a suitable .gitattributes file has been prepared but not yet pushed, for a Unity project using Github, Git LFS and SourceTree?
Software/services used:
Unity 2020 LTS
Github
Git LFS, which is part of Github
SourceTree
Links I'm using:
Githubs own migration tutorial
Githubs documentation for the migrate command
A .gitattributes file, which handles casing-differences in extensions using RegEx (I think).
Another answered question very much like this one.
I also took a look at BFG Repo-cleaner, but it seems a bit much for this task.
Motivation for posting
I've been trying to find a guide describing the best way to do this, but most seem to be out-dated or don't include enough information for me to be confident in firing these import-commands on my repo. Others focus a lot on how to set up LFS using a specific server backbone, like Bitbucket Cloud, but I can't find any focusing on Git LFS and SourceTree.
SourceTree has direct integration with Git LFS, but there seems to be no UI-implementation of the migration process for existing files in the repository, so I think I have to rely on the terminal for this part (which I honestly haven't had to use in years, so there's that).
I also have a question about a command for this that I don't see mentioned in my contexted searches: --fixup
The setup
It's not a huge repo; it's a main branch with a few dead branches that don't matter. I just want all the files with certain extensions converted to LFS. My initial thought was to do the migrate-command with --norewrite, because I liked the idea of compacting all the changes into one commit and have no changes to the commit history, but when I realized that means the files would have to stay in the repo for posterity, I changed my mind. I want the repo to shrink, as well, which means I want to replace the files with pointer-files back through the commit history, in order to eliminate the actual files from the repo completely, so they only exist in the LFS-storage.
My questions and options, as I see them
In that other answered question I linked to, a full answer isn't given, but it's very close. Though the answer is very informative, it doesn't answer these questions:
How to handle case-sensitivity surrounding extensions when writing migrate-commands with --include and --exclude options? Do I need to either go through all existing files in the repo and ensure a similar casing in order to do one-liners, or alternatively fire a separate line for each permutation of the extension I find in the repo? (ignore this question, if --fixup understands the casing-format mentioned in 2. and works for my purposes).
I see that there is a --fixup option for the migrate command, which isn't mentioned in the search results I'm getting with the given context, except in Githubs documentation for the migrate-command. It says:
"Infer --include and --exclude filters on a per-commit basis based on the .gitattributes files in a repository. In practice, this option imports any filepaths which should be tracked by Git LFS according to the repository's .gitattributes file(s), but aren't already pointers."
Is there some reason why the --fixup option isn't recommended anywhere, when it seems to do exactly what I need? Does it not rewrite the history, or something?
I hope it works, because since --fixup reads the .gitattributes files, it should be able to read the different casing-options from the casing-format in the .gitattributes files. Then I don't have to worry about missing files due to different casings, like when using the --include option.
This is the casing-format used in the .gitattributes file (example for .wav files):
*.[Ww][Aa][Vv]
It works for .gitattributes' normal workings, but doesn't work when you use the format for the --include or --exclude options for the migrate-command, e.g.:
git lfs migrate import --include="*.[Ww][Aa][Vv]"
...does not work. This is what gives the casing-issue mentioned in 1.
I have LFS initialized. I have my .gitattributes file (uncommitted) at the root of the project. So, committing and pushing .gitattributes, and then doing 2. seems to be what I want, right? I should be able to open the terminal in SourceTree, and put in this line:
git lfs migrate import --fixup
or do I need --everything, in order to affect all branches?:
git lfs migrate import --everything --fixup
Also, if --fixup doesn't work, is it just a bunch of these?:
git lfs migrate import --everything --include="*.WAV"
git lfs migrate import --everything --include="*.wav"
...followed by a:
push --force
or
push --force --full
???
That's about where I'm at. I'm not entirely sure which way to go here, or how each of these commands affect the result. I'd appreciate any input on what would be the best course here. If anything, I've tried to be as informative as I can and include the best sources I've found on the subject, to help anyone else asking the same questions.
EDIT: I found this issue at the Git LFS repository, which describes a caveat with the --fixup option; it takes into account when the existing files were added to the repo, and if they were added before the changes to the .gitattributes-file, then they aren't included. So, it is recommended to either rebase, or use filter-branch or filter-repo, in order to add/change the .gitattributes file at the root commit, so that the --fixup option will register the files. The issue deals with some more caveats, like having to uninstall LFS first, but eventually found that solution. This is all just to avoid having to do separate calls for each extension-casing permutation. I don't want to do any of those suggestions, since some seem to run into trouble with them, and I can't get --fixup to work with info, meaning I can't preview what it'll change, so I'm going with --include calls, and just searching up all the current permutations of the extensions of the existing files, and doing --include calls for those. Please, if you do have any good information on the subject, I (and probably many others) would love to hear some easier solutions to this problem.
Thanks in advance and best regards, Jonas Tingmose.

Comments in git (egit)

We recently moved to git from svn (both using Eclipse). I am in the (perhaps bad) habit of writing my Java code first, getting everything to work and then going back and adding comments. In SVN this was easy. I would just create a Fisheye review with my Jira task. The review would have a list of all the files I changed and methods I added or modified. I would note it and abandon the review. Then I would edit all the files listed and add the comments.
However, Fisheye does not (I believe) work with git. I could do a git status to see the files I changed but the local branch is already updated so it will not list any files. And all it does is tell me I am something like one commit ahead of the remote branch but does not list any files.
Is there some way to see a lit of the files I have changed with git so I can add comments? And when I say I wait for my comments I really mean mostly for added classes and methods. If I do something like add a line or two to a method I will generally add the comment too.
changing comments on git commits is not that easy. Each git commit has a sha-checksum which also includes the previous git commit. If you change a commit you change the current commits sha-checksum. therefore you create a new commit. All following commits of your branch must now be rebased on top of this new commit.
The command line provides the git rebase -i [commitid] where you can do lots of modifications including changing comments on commits. I never did this with a GUI but egit might support that too. Just refer documentation on egits rebase feature.
I found out how to do this.
The "Synchronize Workspace" in eclipse appears to show all the changed files not yet pushed remotely. I have not done any pushes, so this showed me what files changed.

How to ignore eclipse metadata but preserve the template?

I've got an ARM project in Eclipse...Actually, I'm using the STM Workbench packaging of Base-CDT-Eclipse.
I'm working with a few other guys and we're using a git server to push and pull from.
However, everyone has a little bit different setup as far as where their toolchains are, OS's, etc.
This is causing trouble, because we're git dummies, and when we push changes after working locally, we do
git add .
git commit -m "some message"
git push origin master
And when we pull changes, we just do
git pull origin master
And pray that there no one else did anything in the meantime, because we're afraid of merging differences, but that's a different story.
Anyway, this whole project has a few sub directories that include things like datasheets, Word documents, and what-not...but, it also includes the metadata for the Eclipse project. So, the last person to commit also pushes their unique settings for things like tool-chain path, preferred builder, etc. This breaks the other guys' setup and after each pull, everyone else has to manually update their project settings to fix this.
So, what files are special to Eclipse for project settings and how can I tell git to ignore these files if they already exist? They need to be available for, say, a git clone but they need to be ignored for subsequent git push's and git pull's.
If you need the setting file and not rename it and it's ok forsetting file need not to do version control, so there is a way by .gitignore with below steps:
Create a .gitignore file. touch .gitignore
Edit and save the .gitignore file
.gitignore
filename
Remove the caches from version control. git rm --cached filename
Commit and push
You can ignore those files changes locally with:
git update-index --skip-worktree -- .project
git update-index --skip-worktree -- .classpath
See: "Difference Between 'assume-unchanged' and 'skip-worktree'", it should better resist to git pull.
Another option would be to a content filter driver which generates (automatically on git checkout) a .classpath if it does not yet exist.
That allows you to version a .classpath.tpl template, and you can keep your actual .classpath completely private (and in your .gitignore)
See this answer for more.

How to remove a specific directory from GitHub using Eclipse

I've looked all around for a few days now trying to figure this out because our .gitignore even though it lists /bin/ folder it still keeps freaking commiting the whole folder and its getting annoying.
Now we have a whole bunch of crap in a /bin/ folder in our GitHub repository and I have no idea how to remove it. I've tried looking at other peoples examples but they keep talking about a shell command that I don't have in eclipse (or at least don't know how to access)
The sad news is that if a file has been already committed to GitHub, git will continue to version that file.
This means if I commit the entire bin/ then add it to .gitignore, the files will still persist in GitHub. And, if these files in bin/ change, they will also be pushed in the commit because they are versioned.
Luckily, you can remove files and directories from GitHub completely. You need, though, to get to a command line running git. If you have the GitHub application installed, that probably means you have git.
Open command prompt in Windows or Terminal in Mac OS.
Navigate to the directory (ie. cd ~/Workspace/Project) and run the following:
git rm bin/* -f
git commit --amend
git push -f
This should work. Check out this article on the GitHub that also outlines the process.
Hope this helps you!
Disclaimer: always make sure you do your research before working with git. If you have various branches / other complicated stuff going on, this process might be different

Half-ignored files in VCS - is this supported?

I am using Eclipse and Subversion for Java development, and I find myself wishing for a feature in version control systems (one that is not available in SVN, to the best of my knowledge).
I would like my project settings files to be half-ignored. To be more precise, I want them to be available in VCS, I want merge to occur when someone checks in changes, but. I want my own changes ignored unless I very explicitly tell the system to take them.
This would allow me to have my local paths (and other settings) in my local configuration w/o screwing up other people's configuration. But, when I have a substantial change, I can still check it in (very very carefully, may be temporarily removing my other local changes) and have it delivered to other people.
Now, the actual question: is there any VCS that supports this feature? Or may be I am missing something in SVN? How do other people solve this problem in Eclipse?
Yes, Git support that feature through filter driver (a clean script can run upon commit, allowing you to clean the content from any of your changes if you want).
But another way would be to never version that setting file, and only version:
a template file
a value file
a script able to replace variables in the template files with the values from the value file, in order to generate the actual (and "private", as in "not versioned") setting file.
That way, you can modifying it at your heart's content without ever committing your changes.
.gitignore for git, .hgignore for mercurial and file paths and patterns can be added that will not be committed. There similar in SVN but i never worked out how to use it myself but my sysop did set it up form me.
git supports this with
git update-index --assume-unchanged <file>
and the complementary
git update-index --no-assume-unchanged <file>
See http://blog.pagebakers.nl/2009/01/29/git-ignoring-changes-in-tracked-files and http://kernel.org/pub/software/scm/git/docs/git-update-index.html#_options for more details.