git diff displaying wrong file mode - instead of 775 displaying 755 - linux

I have recenlty changed system and few files started appearing in git diff. Its due to mode change and am ok with that for now.
I am wondering why git diff displaying mode 755, when it supposed to 775. In below screen all linux command says it is 775, but git diff says it is 755.
OS is Ubuntu 22.04.

Git only stores one bit (as in binary digit) of "mode" information per ordinary file: "executable" (+x) or "not executable" (-x). This single bit of mode information is, however, stored as mode 100755 (+x) or mode 100644 (-x).
It's no coincidence that 100755 corresponds to a Linux 0755 file mode: in fact, the 100 part is from S_IFREG in <sys/stat.h>. Likewise 100644 corresponds to a file whose mode is 0644 or rw-r--r--. In the distant past, Git did store more mode bits per file. But this was discovered to be a mistake, so now Git stores only the one mode bit—but uses the same encoding it used back when it stored more bits.
The actual file permission bits that you'll find on disk will depend on your umask setting, not on the mode 100755 setting. If you have umask 022, Git will create executable files with mode 0755 or rwxr-xr-x. If you change your umask to 002, Git will create such files with mode 0775 or rwxrwxr-x. But the old and/or new mode as shown in git diff output will always be either 100644 or 100755, and that means -x or +x respectively.

When storing a file (blob) in Git, there are only two possible file modes: 644 or 755. That is, Git stores only the executable bit, and if it is set, it stores the latter, and if not, it stores the former. Thus, for diffs, Git will only reflect whether the executable bit is set and will always use one of those two modes.
In the working tree, Git uses the umask to set permissions, which explains why your files are actually 775.

Related

Relsove add merge conflict

I'm merging two branches and getting so many merge conflicts like
CONFLICT (add/add): Merge conflict in pika/static/ckeditor/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
Auto-merging pika/static/ckeditor/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
that they do not fit into my putty terminal. So I aborted the merge and run some git diff commands.
git diff origin/dev-kasitesivu_py_3.7..origin/dev-kasitesivu -- pika/static/ckeditor/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
diff --git a/pika/static/ckeditor/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js b/pika/static/ckeditor/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
old mode 100644
new mode 100755
For a huge amount of files the only change seems to be mode as above (I don't know what it means). I tried to copy the files from the directory running the branch that I want to merge, but git status did not show anything changed. Neither does linux diff-commad.
How can I resolve the conflicts ?
The linux diff command compares file lines. i.e. the contents of the file. Your conflict is one of file permissions. You must select which permissions the files actually need to have. 755 is usually set on directories, but may have been set on the files in your case, by some other process or perhaps a sgid sticky bit.
You should be able to resolve your issue by setting the file permissions on the affected files to the permissions in old mode. Like:
for x in those_files; do chmod 0644 $x; done
Or something of that nature.

Git: Working with executables

I have a project in which there is a .sh file and it has to be in the executable mode once pulled by the others. Now, I already changed its permissions on my local machine. However I want it to be pushed/pulled as executable as well, so that the other users do not have to run chmod command all the time.
I have been informed about two possibile solutions: .gitattributes and git update-index --chmod=+x script.sh, however I am not sure what exactly should I follow, given my condition.
I've seen this post here and this answer there, and I am thinking which one would suit my case more. I want this process to be done automatically, not by the user everytime, added.
Any thoughts?
Since you've tagged this question with linux, you can just check the file in. Now that you've changed it on your computer:
% chmod +x script.sh
Git will notice that the file has changed:
% git status
On branch old2
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: script.sh
And you can diff to see that the file is, in fact, now executable:
% git diff foo.sh
diff --git a/foo.sh b/foo.sh
old mode 100644
new mode 100755
Mode 100644 reflects a non-executable file, and mode 100755 reflects an executable file, similar to the Unix file permission bits. (Had you changed the file in addition to changing the permissions, you would also see the changes.)
When you check this in and your collaborators pull your changes, the file will be made executable for them, too.
Note that this does not work automatically on systems that do not have the notion of an execute bit (ie, Windows), and in that case, you will need to do something with update-index.
Note also that this relies on your system to have configured core.filemode being set correctly. This value should be set to true on all non-Windows systems.
% git config core.filemode
true
If, for some reason, that command returns false and you are on a non-Windows computer, run:
% git config core.filemode true
to re-enable it.
You have to decide which is fit for you. Two methods those you given above they can acceptable and they almost the same.
You should know how to give working permissions to executable files. In Linux, true way to do it is "chmod". Also you can sue git hooks as well. For doing in normal method I preferred this:
git add file.sh #this could be py file or something
git update-index --chmod=+x file.sh #make it executable
git commit -m "here the commit" #commit it
git push #push it
So if you want to do it another way you should try this:
#!/usr/bin/bash
chmod +x file.sh
And you can run it. But before the run it, you should give working permissions to your script that you made for giving working permissions to other scripts :)
Or you can give the permissions dynamically:
su -c 'chmod +x file.sh'
In this way, you should give the working permission for one time and it runs.
Did you consider Git hooks?
Maybe this could be solution for you
.git/hooks/post-checkout:
#!/bin/sh
chmod +x script.sh
Here you can find more about Git hooks.

Linux permission in directories

I installed Apache in my server and it all looks fine. The problem is that everytime I create a folder/file it does not have 777 permission, I need to use chmod to every folder/file I create to assign 777 permission. How can I create a permission rule that will be the default to new files/folders ?
While I agree 777 is not a good idea, the answer is umask:
umask 000
I recommend the following at least so not everyone in the world (well, with access to that machine) can write there:
umask 002
Oh, and these don't inherit by the directory. Use ACLs instead to get inheritence. ACL tools vary from OS to OS. Try "setfacl" or "chacl".
The short answer is that you can't and you shouldn't even if you could. Having any file on the file system with 0777 as the mode is a very bad idea.
The slightly longer answer is that the Apache process controls the mode that it creates new files with as the third argument to open(2) or by using fopen(3). In the latter case, the mode is 0666 by default. Whatever mode is passed in is further modified by the process's umask value. If a process has a sane umask (such as 022), then the result of opening a file with fopen will be a file with its mode set to 0666 & ~022 = 0644. I guess if the process were to use open to create a file with 0777 and the process umask was set to 0, then the file that it creates would have 0777 as the resultant mode.

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.

cygwin sets file permission to 000

I have a folder /cygwin/d/myfolder/
And everytime I save files there, from cygwin if i do an ls -la I see that the files are given permission 000. That actually causes me quite a bit of problem as I rsync this folder to my server and none of the files are accessible. How can I get the files to automatically get a reasonable permission?
Have a read through the answers at this link:
http://cygwin.1069669.n5.nabble.com/vim-and-file-permissions-on-Windows-7-td61390.html
The solution there worked for me also:
Edit /etc/fstab and add this line at the end of the file:
none /cygdrive cygdrive binary,noacl,posix=0,user 0 0
Then close all Cygwin processes, open a new terminal and ls -l on your files again.
Explanation:
By default, Cygwin uses the filesystem's access control lists (ACLs) to implement real POSIX permissions. Some Windows-native program or process may create or modify the ACLs such that Cygwin computes the POSIX permissions as 000. With the noacl mount option, Cygwin ignores filesystem ACLs and only fakes a subset of permission bits based on the DOS readonly attribute.
Check to make sure that your umask is set correctly with the umask command. If your umask is say 0777 that subtracts from the permissions of new files and will end up with 000 permissions. There's probably several other possibilities to consider beyond that.
If your id is not set up correctly in /etc/passwd and /etc/group that can also cause ls to show unexpected results. Check the permissions of the folder. Also check the Windows permissions with the getfacl command. Maybe also check the mount command.
In above answer, solution was proposed:
Edit /etc/fstab and add this line at the end of the file:
none /cygdrive cygdrive binary,noacl,posix=0,user 0 0
And in that answer there was this comment:
When I try this, all my files are -rw-r--r-- no matter what chmod() I do. I can't mark the files as executable; it just reverts to 0644. (umask==0022)
I had this same problem, but it manifested in inability to execute DOS batch files (*.bat) when running Cygwin ksh or mksh. I stumbled across this website: http://pipeline.lbl.gov/code/3rd_party/licenses.win/cygwin-doc-1.4/html/faq/ which contains this helpful advice:
Note that you can use mount -x to force Cygwin to treat all files under the mount point as executable. This can be used for individual files as well as directories. Then Cygwin will not bother to read files to determine whether they are executable.
So then cross-referencing with this page - https://cygwin.com/cygwin-ug-net/using.html#mount-table - with its advice:
cygexec - Treat all files below mount point as cygwin executables.
I added cygexec to fourth field of my fstab. This did it. My .bat is now executable inside ksh/mksh, which is necessary since I'm running a Jenkins job that calls a Korn shell stack 3 files deep, that I have no modifiable control over. I just needed the .bat to run!
Update: the solution above wasn't quite what I needed, on further testing. It resulted in some executables such as javac and cl to behave oddly (the utilities would print their usage and exit). I think what I needed instead of 'cygexec' was just 'exec'. As the same page notes:
exec - Treat all files below mount point as executable.
On my Win7 PC files were usually
----------+ 1 David None 69120 Jun 17 13:17 mydoc.txt
I tried all of above no luck
Turned out I still had some old historical mount entries in my .zshrc
I deleted these and Bob's your Uncle problem gone away!

Resources