Does git create new files during merge or overwrite existing ones - bash

I have a script test.sh
#!/bin/bash
echo start old file
sleep 20
echo end old file
in the repository which I do execute, and in the mean time I git merge other-branch changes like
#!/bin/bash
echo start new file
sleep 20
echo end new file
into the current branch.
It seems that git on Unix (?) does not directly overwrite the existing file node (?) and does instead rm test.sh and creates the new file.
In that way its guaranteed that the script execution will always read the initial file test.sh and terminate with echo end old file.
Note: On my system (Ubuntu 20.04), while executing the script and directy overtwriting the content in an editor, results in executing the new code, which is bad...
Is that correct and is it also correct on Windows with git-for-windows?

I can't answer regarding Windows, but on Ubuntu 18.04 I can confirm that a git checkout or git merge will delete and recreate a changed file, rather than editing it in place. This can be seen in strace output, for example:
unlink("test.sh") = 0
followed later by
openat(AT_FDCWD, "test.sh", O_WRONLY|O_CREAT|O_EXCL, 0666) = 4
It can also be seen if you create a hard link to the file before the git command and then look again afterwards, you will see that you have two different inodes, with different contents. This is to be expected following deletion and recreation, whereas an in-place edit would have preserved the hard linking.
$ ls -l test.sh
-rw-r--r-- 1 myuser mygroup 59 Jun 5 17:04 test.sh
$ ln test.sh test.sh.bak
$ ls -li test.sh*
262203 -rw-r--r-- 2 myuser mygroup 59 Jun 5 17:04 test.sh
262203 -rw-r--r-- 2 myuser mygroup 59 Jun 5 17:04 test.sh.bak
$ git merge mybranch
Updating 009b964..d57f33a
Fast-forward
test.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
$ ls -li test.sh*
262219 -rw-r--r-- 1 myuser mygroup 70 Jun 5 17:05 test.sh
262203 -rw-r--r-- 1 myuser mygroup 59 Jun 5 17:04 test.sh.bak
You mentioned in a comment attached to the question that it is related to Overwrite executing bash script files. Although it would seem not to be the best idea to run a git command affecting a script which is currently still being executed, in fact the delete and recreate behaviour should mean that the existing execution will be unaffected. Even if the bash interpreter has not yet read the whole file into memory, it will have an open filehandle on the existing inode and can continue to access its contents even though that inode is no longer accessible via the filename that it had. See for example What happens to an open file handle on Linux if the pointed file gets moved or deleted

On Windows with git-for-windows I see the same behavior:
$ mklink /H test.sh.bak
$ fsutil hardlink list test.sh.bak
test.sh.bak
test.sh
$ git merge test
$ fsutil hardlink list test.sh.bak
test.sh.bak
Meaning the hard link did not get preserved, meanin a new file has been created.

Related

Shell Script to Move a File Into Another User's Directory?

I'm running a Ubuntu 16.04 server. On my server, I have a file in directory /home/userA/dirA:
userA#myUbuntu:~$
userA#myUbuntu:~$ pwd
/home/userA
userA#myUbuntu:~$
userA#myUbuntu:~$ ls -l
total 8
drwxrwxr-x 3 userA userA 4096 Feb 17 14:13 dirA
userA#myUbuntu:~$
userA#myUbuntu:~$ ls -l dirA/
total 7796
-rw-rw-r-- 1 userA userA 1234 Feb 17 14:05 theFile.txt
userA#myUbuntu:~$
Note the ownership here; user userA owns the file and the directory where the file resides.
I need a shell script that moves theFile.txt to another location, into a directory that is not owned by userA. Here's my script:
#!/bin/bash
echo "Attempting to move file..."
{
sudo mv /home/userA/dirA/theFile.txt /home/userB/dirB/.
} || {
echo "Failed to move file!"
}
...and the output:
userA#myUbuntu:~$ ./myScript.sh
Attempting to move file...
Failed to move file!
userA#myUbuntu:~$
As you can tell, the script runs as userA. I don't want to run it as root.
So I'm assuming the script is failing because of the permissions; a script run as userA does not have permission to move a file into a directory owned by userB. I've been trying all sorts of variations of the sudo command and others, but to no avail. I've also tried goofy workarounds, like copying the file to /tmp (that works) and then doing a chown to change file ownership (that doesn't work). But there's got to be a way to neatly do this. Any ideas?
Create a new group, add both users into it and set the appropriate permissions. After that you will be able to move files between folders.

Use "perl6" command with Git Bash on windows

Using Windows, I installed Rakudo Star and Git and ensured that C:\rakudo\bin and C:\rakudo\share\perl6\site\bin are in my Path environment variable.
Now, typing perl6 inside Git Bash afterwards gives the command not found error, while the command does work inside powershell and cmd. Typing echo $PATH inside Git Bash confirms again that the folders above are in my path variable here as well.
How can I get the perl6 command working inside Git Bash?
Note: Using moar (moar.exe) which resides in the same folder as perl6 works as well in Git Bash. Also hitting Tab show the autocomplete suggestion for moar, it does not do that for perl6.
Bash doesn't run Windows batch files, so you'll have to work around that.
An easy solution might be to add something like this you your .bashrc:
alias perl6='cmd /c perl6.bat'
Alternatively, you can convert perl6.bat to a shell script and put it somewhere in your $PATH.
I use the following:
#!/bin/sh
PATH=/cygdrive/c/rakudo/bin:/cygdrive/c/rakudo/share/perl6/site/bin:$PATH
unset HOME
moar --execname="$0" \
--libpath='C:\rakudo\share\nqp\lib' \
--libpath='C:\rakudo\share\perl6\lib' \
--libpath='C:\rakudo\share\perl6\runtime' \
'C:\rakudo\share\perl6\runtime\perl6.moarvm' \
"$#"
This is using Cygwin; you may need to adapt it a bit for Git bash (I don't know, no experience with it).
Alternatively, if you're using Windows 10, I can recommend installing WSL, and using perl6 in a WSL bash prompt instead. This runs much smoother for me than the Windows version under Cygwin.
I tried to install perl6 from the link you provided and I can confirm the same behavior on Cygwin on Windows 10.
If I type in the Cygwin terminal window:
$ perl6
-bash: perl6: command not found
$ echo $PATH
/usr/local/bin:/usr/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/WINDOWS/System32/WindowsPowerShell/v1.0:/cygdrive/c/WINDOWS/System32/OpenSSH:/cygdrive/c/Users/Bruker/AppData/Local/Microsoft/WindowsApps:/cygdrive/c/rakudo/bin:/cygdrive/c/rakudo/share/perl6/site/bin
$ cd /cygdrive/c/rakudo/bin
$ ls -l
-rwxrwx---+ 1 SYSTEM SYSTEM 930663 May 11 2017 libgcc_s_seh-1.dll
-rwxrwx---+ 1 SYSTEM SYSTEM 136146 Mar 30 20:55 libmoar.dll.a
-rwxrwx---+ 1 SYSTEM SYSTEM 56978 May 11 2017 libwinpthread-1.dll
-rwxrwx---+ 1 SYSTEM SYSTEM 7021172 Mar 30 20:55 moar.dll
-rwxrwx---+ 1 SYSTEM SYSTEM 64066 Mar 30 20:55 moar.exe
-rwxrwx---+ 1 SYSTEM SYSTEM 126 Mar 30 20:56 nqp.bat
-rwxrwx---+ 1 SYSTEM SYSTEM 126 Mar 30 20:56 nqp-m.bat
-rwxrwx---+ 1 SYSTEM SYSTEM 242 Mar 30 20:56 perl6.bat
-rwxrwx---+ 1 SYSTEM SYSTEM 248 Mar 30 20:56 perl6-debug-m.bat
-rwxrwx---+ 1 SYSTEM SYSTEM 242 Mar 30 20:56 perl6-m.bat
$ cat perl6.bat
# "C:\rakudo\bin\moar" --execname="%~dpf0" --libpath="C:\rakudo\share\nqp\lib" --libpath="C:\rakudo\share\nqp\lib" --libpath="C:\rakudo\share/perl6/lib" --libpath="C:\rakudo\share/perl6/runtime" C:\rakudo\share\perl6\runtime\perl6.moarvm %*
Notice that the paths in the bat file are not cygwin paths. So that might explain why it does not work..
For example:
$ "C:\rakudo\bin\moar"
-bash: C:\rakudo\bin\moar: command not found
$ /cygdrive/c/rakudo/bin/moar
ERROR: Missing input file.
USAGE: moar [--crash] [--libpath=...] input.moarvm [program args]
moar --dump input.moarvm
moar --help
[...]
Update:
I also tried install Git Bash, and then from the MINGW64 terminal window:
$ echo $PATH
/c/Users/Bruker/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/usr/bin:/c/Users/Bruker/bin:/c/WINDOWS/system32:/c/WINDOWS:/c/WINDOWS/System32/Wbem:/c/WINDOWS/System32/WindowsPowerShell/v1.0:/c/WINDOWS/System32/OpenSSH:/c/Users/Bruker/AppData/Local/Microsoft/WindowsApps:/usr/bin/vendor_perl:/usr/bin/core_perl
$ PATH=/c/rakudo/bin:$PATH
$ perl6
bash: perl6: command not found
$ moar
ERROR: Missing input file.
USAGE: moar [--crash] [--libpath=...] input.moarvm [program args]
moar --dump input.moarvm
moar --help
[...]
Note that moar is an .exe file while perl6 is a .bat file.
Also it seems perl6 is not "offical" for Cygwin yet according to this issue.

Soft symbolic link mac permission denied

i've been banging my head for an hour now.
Context : I decided to put my dotfiles in the repo and symlink them.
I tried to symlink and got permission denied so I decided to try a simple symlink and it just won't work.
I created a testFolder( /Users/myUserName/testFolder ) :
drwxr-xr-x 3 myUserName staff 102 24 Nov 16:47 testFolder
Inside there is a test file :
-rw-r--r-- 1 myUserName staff 53 24 Nov 16:47 test.sh
So I created a symlink to test symlinks in the parent folder with this command :
myUserName testFolder $ ln -s test.sh ../test.sh
I go to the parent folder and get this symlink :
lrwxr-xr-x 1 myUserName staff 7 24 Nov 16:52 test.sh -> test.sh
For some reasons, when I try to edit it, I get Permission denied.
If I symlink it in the same folder, I can edit it and no permission denied!
Has any body encountered this? I must be doing something wrong.
Thanx!
Symlinks with relative paths are resolved relative to the directory the symlink is in, not relative to the directory you were in when you created them. So when you run this:
ln -s test.sh ../test.sh
You’re creating a symlink that points to a file named test.sh in the same directory as the symlink, i.e. itself. What you want to do is this:
ln -s testFolder/test.sh ../test.sh
Which creates a symlink to test.sh in the testFolder sub directory under the directory the symlink is in.
Ah! Found the answer! You can't put relative links in the first argument!!
You HAVE to put absolute path in the first argument like this :
$ ln -s absolute-path-to-source ../test.sh

Create files in my shell script owned by root without the need for sudo

This might seem a little strange question at first but here me out.
I'm writing a shell script that makes up a file system that'll get compressed back into an archive and it needs some files in it to be owned by the root user. This whole thing is going to be automated soon but right now it's a bit of a problem because if I use sudo I need to enter in a password.
Seeing as the files are created beneath my own home directory for which I have full access I thought perhaps I can change their ownership to a root user. Is that possible?
If I try it normally I get "Operation not permitted". Maybe there is an alternative?
You can do what you want using fakeroot. It's a library that makes programs think they're running as root, when they are not. IIRC, it is used by dpkg to allow non-root users to build .deb packages that contain root-owned files.
Check out this shell script:
#!/bin/bash
mkdir image
touch image/user-owned
touch image/root-owned
chown renato.renato image/user-owned
chown root.root image/root-owned
tar cf image.tar image
Normally, I would only be able to create this tar archive as root. However, if I use fakeroot:
$ fakeroot ./create-image.sh
$ tar tvf image.tar
drwxr-xr-x root/root 0 2014-04-09 01:09 image/
-rw-r--r-- root/root 0 2014-04-09 01:09 image/root-owned
-rw-r--r-- renato/renato 0 2014-04-09 01:09 image/user-owned
However, the files on the disk are still user-owned, so no security risk here:
$ ls -l image/
total 0
-rw-r--r-- 1 renato renato 0 Abr 9 01:09 root-owned
-rw-r--r-- 1 renato renato 0 Abr 9 01:09 user-owned

Unable to make file editable on Mac OS X

I'm trying to edit the httpd.conf file located in /private/etc/apache2, and I can't figure out how to get permission to write
I've done
$ cd /private/etc/apache2
$ sudo chown bdh httpd.conf
$ ls -lash
0 drwxr-xr-x 13 root wheel 442B Jun 7 00:11 .
0 drwxr-xr-x 93 root wheel 3.1K Jun 26 10:51 ..
0 drwxr-xr-x 13 root wheel 442B Jan 3 16:26 extra
24 -r--r--r-- 1 bdh wheel 24K Jun 7 00:11 httpd.conf
...etc...
$ vim httpd.conf
and it says "httpd.conf" [readonly] 677L, 24330C
tried cping to the desktop, but I cant get permission to edit it there either
I'm pretty new to using the terminal, is there some other command I can use?
It is normally unnecessary and undesirable to alter access permissions to edit a file. To edit a file that requires administrator (or other user) privileges without altering the access permissions, use:
sudo -e /private/etc/apache2
Sudo's -e option tells it you want to edit the given file.
This command copies the file and makes it writable by you, tells the editor specified with the SUDO_EDITOR, VISUAL or EDITOR environment variables (they're checked in that order) to edit the file, and when the editor exits, the file is copied back to the original without altering its access permissions.
See the sudo man page for details: x-man-page://8/sudo
The chmod command is what you're looking for I believe: http://en.wikipedia.org/wiki/Chmod
chmod 777 will let anyone read, write or execute for instance.
As richardhsu correctly added, 744 is RWX, R--,R-- and thats probably what you want.

Resources