Remove committed code from an old multiple file commit - windows

In one of the file of my project there is the code of the protection dongle. Normally before committing I set the code to 0, but once I forgot to do that and now the code is stored the local git archive. I don't want to discharge all the history (I made some other commits after), but I only want to remove that specific file from that specific commit (I know its SHA) leaving all the other committed file in the same commit.
Is it possible? If yes, how can I do it?
I followed the steps indicated here: https://sethrobertson.github.io/GitFixUm/fixup.html#change_single_deep_simple (my case should be "Changing a single commit involving only simple commits") but I don't know how to remove the file with the code.

Following the link Remove sensitive files and their commits from Git history I got here https://help.github.com/articles/remove-sensitive-data/ where there is the tool named BFG. It could be maybe brute force, anyway it replaced all the occourences of the secret code.

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.

Git for Windows - prevent .pack file date/time modification

I am using Git for Windows (version 2.15, but the same issue occurs in 2.14 and I think older versions as well) and I noticed a rather annoying behavior: When I perform some basic git operations*), the modification date of the .git/objects/pack/pack-*.pack file changes. The file itself remains unchanged, but the last modification date field gets updated, which causes my backup software to think the file was changed and needs to be added to my differential backup. Because my .pack files are rather large, this increases the size of my daily backups significantly. Is there a way to prevent this behavior? That is, keep the pack file completely unchanged, including its metadata, until I perform a git gc or git repack?
Unfortunately, I wasn't able to pinpoint which operation causes this behavior. When it happened today, I only used git status, git log, git add, git mv and git commit and nothing else and the date/time got changed, but when I tried to replicate the behavior on my yesterday's backup, the date change didn't occur. I guess next time I will run Process Monitor and watch accesses to the file, but in the meanwhile, does anyone have an idea of what might be causing this problem? Thanks.
Instead of referencing your Git repo itself for your backup program to process (with the date issue), you could have:
a task which does a git bundle of your repo (that generates only one file)
your backup program would back up only that one file.
That way, you bypass entirely the modification date issue for those pack files.
You can either save and keep only one copy of a full bundle of the repo.
Or make incremental bundles.
In the end it turns out that Edward Thomson's answer explains why no "real" solution is possible. However, to facilitate my needs, I wrote a simple Windows command-line application which scans through a tree of directories, locates possible Git repositories, locates their packfiles and changes the date/time of each .pack file to that of the respective .idx file. So far it seems to run OK. I did not encounter any garbage collection issues yet, anyway. I did not release the tool yet, because I rather suspect no one else cares, but if someone is interested, I can upload it somewhere.
Apparently, someone is interested. So the program is released as of now. Not on GitHub, but still as open source, under the 3-clause BSD license. Download the binaries here: https://www.pepak.net/files/git/gitpacksync-0.01.zip
and the source code here: https://www.pepak.net/files/git/gitpacksync-0.01-source.zip
If you try to disable this then you would be prone to see subtle bugs where objects that are still in use will disappear from your repository.
You had trouble pinpointing the exact operation because every operation that adds files will do it.
This is very much intentional - Git refreshes the timestamps of objects in the database (updating the timestamp on either loose objects or packfiles) to know when an object was last written. Whenever you create a new commit, it will update the timestamp on all the files that contain objects hat were referenced.
This is important as it helps the tools that remove data (like prune) avoid race conditions: an object may be dereferenced and then re-referenced. Prune will also look at the timestamp, so by touching the file, it will not be eligible for garbage collection.

Best practices for Xcode + Git for multi-developer projects

I can create a repo and use GitHub / BitBucket fine for my own projects. I have had problems when collaborating with other developers or trying to fork a project on GitHub.
I am aware of other answers like Best practices for git repositories on open source projects but there are OSX / Xcode specific problems I want to know how to solve.
.DS_Store files can be a pain. You can use .gitignore to prevent, but what happens if they have already been included, or another developer adds them back in through a clumsy git command?
The .xcodeproj will have changes to the directory names and developer profiles for the other person. What's the best way to do merges or to avoid conflicts?
If I have forked or pulled from a github project, how can I clean up these issues and also minimise merge conflicts for the maintainer?
If people have an example .gitignore created for Xcode, or scripts they use to initialise their repos then that would be great!
Put .DS_Store in .gitignore. Then, if you haven't already, add .gitignore to the repo. (You should not ignore .gitignore.) Now all developers will ignore .DS_Store files. If any were added to the repo erroneously before you put .DS_Store in .gitignore, you can now remove them (in a commit) and they should stay out.
The xcodeproj is a directory. The only file in this directory that must be in the repository is the project.pbxproj file. I generally ignore all of the others by putting these lines in my .gitignore:
*.xcuserstate
project.xcworkspace/
xcuserdata/
You should avoid putting absolute paths in your build settings. Use relative paths.
Your Debug and Release builds should use iPhone Developer as the code signing identity, so that Xcode will automatically select the local developer's profile. When you want to create an IPA (for distribution), Xcode will offer to re-sign it with a different identity, at which point you can choose your distribution profile if you need to.
If you're trying to use a project from github that has made these mistakes, you can try to get the maintainer to fix them, or you can make sure you don't touch the .DS_Store files and the code signing identities in the same commits that you want to send upstream.
For the 2nd issue regarding the .xcodeproj and merge conflicts.
Using a .gitattributes file to specify that merge conflicts for all .pbxproj files should be handled using the merge=union strategy, which should mean that Git knows to merge in the changes from both sides of the conflict, taking the upstream changes first.
This article explains it in a bit more depth
I'll try one by one:
I. You need to use git filter-branch only if you need to remove the files from your history completely. If those files do not contain any credit card information, then i think the following should be enough:
git rm --cached .DS_Store
git commit -m "{Your message}"
then add this file to .gitignore and commit it.
This will commit the removal of the file from the repository but will keep the file in working directory. If you push it though and then somebody else will pull this commit, they might have their file removed, so you MUST communicate this.
By committing .gitignore you will prevent other developers from adding this file again.
If you're not a maintainer, then i don't think you should do anything, but address this issue to the maintainer.
II. I'm a strong believer that hidden files of any nature are most of the time not supposed to be put into the repository exactly for that reason. Therefore i think that you should do the same thing with .xcodeproj as with .DS_Store and put it into .gitignore and commit it. .gitignore is the exception for the rule above.
III. If those files are properly ignored , then there will be no issues in future with them. If they are already in the repo and somebody wants do such cleanup it should be done by maintainer and communicated inside the team.
Hope that helps!
git filter-branch might help you to remove unwanted files (.DS_Store files) from your repository -- see e.g. https://help.github.com/articles/remove-sensitive-data
If a clumsy git commit has added files you should be able to replay the corrected changesets onto a clean repository.
You're right in the sense that if a .DS_Store is already added the .gitignore won't be of much help however I think this is still a good resource for you and others.
When I start a project, I normally look at this list to see if there is a good .gitignore already existing. More specifically for you, this one is the Objective-C .gitignore.
Hopefully those resources are of some use.
As a Mac user you should download a tool like SourceTree which supports Git Flow. Git Flow will help you establish some best practices around how your collaborators will commit code to the repo and at the very least make merge conflicts less frequent and more manageable. For a set of gitignore files for various project types you can go to GitHub and download one that is ready to go. For Xcode they have it listed as Objective-C.gitignore. That is a good starting place and it even covers Cocoapods. If you're using external libraries, your project should use CocoaPods so that you can isolate that code and keep it outside of your repo and avoid git submodules.
Now when you find a file has made it into your repo like .DS_Store just remove it, and move on. Make sure you add it to the .gitignore file that is checked into the project.
As for xcodeproj... there shouldn't be that much customization within the file that is user specific since the above mentioned gitignore filters that out. If a scheme is to be shared make sure you check shared under Manage Schemes and you will check in files in that subdirectory. You should be using automatic selection of certificates so the only real choice is Developer or Distribution. You should also take advantage of variables provided within Xcode that avoid hardcoding complete paths. When trying to think of an example Plists came to mind, in this case, you might have written /Users/me/MyProject/Resources/MyProject.plist, but instead should use $(SRCROOT)/resources/MyProject.plist.

TortoiseSVN and renaming author

I working on a company machine and cannot change the name of the windows username. I am running TortoiseSvn locally and I would like to change the commits to my name. I do not want to right click each commit and manually change the names. Is there a way to do this? I know that there are a couple of threads about this but there are no solutions.
Yes, there is a way to do it, but you probably can't.
In Subversion, there are two types of properties: File properties that are revisioned with the file itself, and Revision properties that are attached not to a file, but to a revision. These are not versioned.
There are several standard revision properties:
svn:log: This is the commit comment.
svn:author: This is the user who made the commit.
svn:date: This is the date and time stamp of the commit.
You can change any of these revision properties with this command:
$ svn pset svn:log --rev-prop -r193 "The commit comment for revsion #193 is this!"
It would be fairly simple to write a script in PowerShell or Python or Perl to do this to a whole bunch of revisions at once. However, you can imagine what type of havoc this could wreck if you could change the date, authorship, and commit comment of any Subversion revision at whim.
Therefore, in order to be able to use a rev-prop change, the repository must have a hook to allow you to do this. This is the only case where you must have a hook to explicitly allow a permitted action. And, of course, it is highly doubtful that you will have the ability to create such a hook.
Now, I'm assuming you were talking about already committed revisions. If you are sharing a working copy, and you make changes, and then commit those changes along with everyone else, you're using Subversion all wrong.
Each user should have their own working directory where they can make changes. This way, the repository will record who did the commit without any shenanigans.
If you simply want to checkout from the repository with a name other than your Windows name, you can save your authentication on your local machine, and Subversion will use that authorization when it does checkouts from that repository.
I believe that authorizations are stored under the %HOMEPATH%.subversion\auth directory. It shouldn't take too long to find the file with the authorization and delete it. Then, when you checkout the next time, you need to specify the user and password and save the credentials. After that, that's what TortoiseSVN will use by default when you use that repository.
That's three different answers covering three different situations in using Subversion and credentials. If I didn't answer the correct scenario, edit your question and explain exactly what you mean and what you want to accomplish. The situation you describe isn't very clear.

Is there a way to do a partial checkin in TFS?

I have a file that has two independent modifications. I would only like to commit one of them.
Is there any way to only check in part of a file (without me modifying or shelving/unshelving it)?
Essentially, create a temp file on commit that then gets checked in instead of the file on disk?
No, the only way is to shelve what changes you have, revert back or the previous version and apply the changes that you want to commit. After committing them, revert back to the shelved version.

Resources