Git delete all unmodified files - linux

I am using git in my project at Linux platform. I have plenty of files in a particular directory. I modified some 50 above files in that directory and didn't stage and commit it. I wish to delete all other unmodified files from that directory? Is there a way to do this, using git and Linux Commands?

Not sure why you would want to do this.... but you can:
# Save changes to stash
git stash save
# Remove everything left
rm -rf ./*
# Checkout (restore) all of the changed files
git stash show --stat | grep -v changed | sed -e 's/|.*$//;' | xargs git checkout
# Restore the changes to those files
git stash pop

git reset --hard [HEAD] should work for you repeated
Repeated question How can I discard modified files?

You can also use more simple commands for this purpose:
git clean -Xfd // capital X
git clean -xfd // lower x
It will clean your working directory from the desired files.

Using git clean is what you want. To remove (-x) those files and directories (-d), run:
$ git clean -fdx
If you use the -X option instead of -x, then the files you have told git to ignore will still be kept (e.g., build artifacts). Recent versions of git require either "-f" (force) or "-n" (dry-run) to be specified.
You should run a dry-run first, to show what will happen, but not actually do anything:
$ git clean -ndx
I use this so often, that I have an alias for this (added to your .gitconfig) to check for files that would be deleted when you run git clean. It's also useful to remind me if I've forgotten to "git add" a file that I want to keep.
[alias]
# list files that would be removed via 'clean' (non-destructive)
ifc = clean -ndx
Then, running git ifc (i.e,. "ifc" = "if clean") shows everything that isn't tracked and could be removed, or isn't tracked and should be added.
https://git-scm.com/docs/git-clean

Related

How to remove a certain type of files and directories from git add before commit?

I added few directories and files by using git add , some of which I don't want in repository.
I would like to remove all the directories and files which either start with . or end with extension yml.
How can I achieve this?
I do not want to undo all the adds but only few adds.
IF you have not committed yet, you can remove from the index any file you need with git reset or git rm --cached if you really want to not track them, which is the case here:
git rm --cached -- .*
git rm --cached -- *.yml

Apply all stashed changes within a subfolder

I had an awful list of old stashes
I have first removed the very old ones
git reflog expire --expire-unreachable=7.days refs/stash
I have one huge stash left, which contains many stashed changes. Some are to keep some other would damage my production system. I went through the diff
git diff stash#{0}^1 stash#{0}
and I know which ones are to keep
I could do
git checkout --patch stash#{0} -- myfilename
to unstash changes on myfilename and is working fine.
However, I have a large folder with many files with stashed changes inside. I would like to apply all of them but only within that subfolder.
I have tried to approach it using wildcards in ksh but I does not work
git checkout --patch stash#{0} -- myfolder/*
results in
error pathspec [...] did not match any files known to git
The solution does not need to be git based, can be a shell script to wrap git calls
Have you tried :
git checkout --patch stash#{0} -- myfolder
without the ending * ?
Chances are your shell expands myfolder/* before executing the git command, and lists the elements which currently exist on disk, which is probably not what you want.

Moving the .git directory wihout moving the files

I am using to track changes to some linux system files (/etc/*), I had the .git in /etc
but now I decided to move it to / as I want to track files that are outside /etc (both /etc and / are in the same filesystems...), I did that and tried to re-add the same files with:
git add $(git status | awk '/deleted/ { print "etc/"$3 } ')
But it does not appear to be working as I hoped as now the are two lists one with a list of "new files" and one with a list of "deleted files", if commit now I will lose all the history
for the files....
What would have been the correct steps?
Thanks!
Antonio
Use git subtree (installation instructions if not already installed).
Create a new repository at / and merge it with the existing one in /etc:
$ cd /
$ git init
$ git subtree --prefix etc /etc master
Ther are similar questions on SO:
My Git repository is in the wrong root directory. Can I move it? (../ intead of ./)
Moving a git repository
And there is no way of chaning directory without losing history of files.

How to apply a git patch on a non-checked out branch?

I am wondering if it is possible to apply a git patch on a non-checked out branch?
I would like to do this because I don't want this patch on my working branch, but on a dedicated branch that I don't use right now. This is a large branch, and checking it out will:
make my exuberant tags useless or broken. It takes long to rebuild them.
also, my kernel will force rebuild if I checkout this branch and roll-back to my working branch...
It's extremely indirect, but possible. You can do it by applying it only to the index.
The easy way:
$ git read-tree <branch>
$ git apply --cached <patch>
$ git update-ref refs/heads/<branch> \
-m "<optional reflog message>" \
$(git commit-tree $(git write-tree) -m "<message>" -p <branch>)
If you want everything to be "cleaner" (i.e. have the reflog look normal for the commit), then here's a longer way, considerably more verbose:
$ git checkout -b temp # Create a temp branch
$ git reset --mixed <branch> # Reset the index to the branch you want
$ git apply --cached <patch> # Apply the patch to the index
$ git commit # Create a commit object
# Move the branch's reference to the new commit
$ git update-ref refs/heads/<branch> refs/heads/temp
# Clean up
$ git checkout --force <original_branch>
$ git branch -d temp
Can you clone from your current repository to another directory, and check out the branch you want to work on there? AFAIK, you can only apply a patch, or cherry pick commits, etc. to the files in your working directory.
For some of the projects I work on, I have multiple copies of a repository on my system, with different branches checked out on each.
I don't think this is possible mainly because of this reason:
How will you deal with a patch failure?

How to track changes of my Linux distrib with git?

I am experimenting some linux configuration and I want to track my changes? Of course I don't want to to put my whole OS under version control?
Is there a way (with git, mercurial or any VCS) to track the change without storing the whole OS?
This is what I imagine:
I do a kind of git init -> all hashes of all files are stored, but not the content of the files
I make some changes to my file system -> git detect that the hash of this file has changed
I commit -> the content of the file is stored (or even better the original file and the diff are stored! I know, that is impossible... )
Possible? Impossible? Work-arounds?
EDIT: What I care about is just to minimize the size of the repository and to have a repository containing only my changes. Having all files in my repository is not relevant for me. For example if i push to github I just want it to contain only the files that has changed.
Take a look at etckeeper, it will probably do the job.
What you want is git update-index --info-only or ... --index-info, from the man page: " --info-only is used to register files without placing them in the object database. This is useful for status-only repositories.". --index-info is its industrial-scale cousin.
Do that with the files you want to track, write-tree to write the index structure into the object db, commit-tree that, and update-ref to update a branch.
To get the object name use git hash-objectfilename.
Here is what we do...
su -
cd /etc
echo "*.cache" > .gitignore
git init
chmod 700 .git
cd /etc; git add . && git add -u && git commit -m "Daily Commit"
Then setup crontab:
su -
crontab -e
# Put the following in:
0 3 * * * cd /etc; git add . && git add -u && git commit -m "Daily Commit"
Now you will have a nightly commit of all changes in /etc
If you want to track more than /etc in one repo, then you could simply do it at the root of your filesystem, except add the proper ignore paths to your /.gitignore. I am unclear on the effects of having git within git, so you might want to be extra careful in that case.
I know this question is old, but I thought this might help someone. Inspired by #Jonathon's comment on the How to record concrete modification of specific files question, I have created a shell script that enables you to monitors all the changes done on a specific file, while keeping all the changes history. the script depends on the inotifywait and git packages being installed.
You can find the script here
https://github.com/hisham-hassan/linux-file-monitor
Usage: file-monitor.sh [-f|--file] <absolute-file-path> [-m|--monitor|-h|--history]
file-monitor.sh --help
-f,--file <absolute-file-path> Adding a file to the monitored files List. The <absolute-file-path>
is the absolute file path of the file we need to action.
PLEASE NOTE: Relative file path could cause issues in the script,
please make sure to use the abolute path of the file. also try to
avoid sym links, as it has not been tested.
example: file-monitor.sh -f /absolute/path/to/file/test.txt -m
-m, --monitor Monitoring all the changes on the file. the monitoring will keep
happening as long as the script is running; you may need to run it
in the background.
example: file-monitor.sh -f /absolute/path/to/file/test.txt -m
-h, --history showing the full history of the file.
To exit, press "q"
example: file-monitor.sh -f /absolute/path/to/file/test.txt -h
--uninstall uninstalls the script from the bin direcotry,
and removes the monitoring history.
--install Adds the script to the bin directory, and creates
the directories and files needed for monitoring.
--help Prints this help message.

Resources