20. Moving files

Goals

  • Understand how to move files within the repository.

I'm pleased with the CSS modifications we've made, but there's one more thing I'd like to address before we merge our changes into the main branch. We should rename the hello.html file to index.html and moving our styles file into a dedicated css directory.

01 Examining the history of changes in a specific file

Git provides the capability to examine the change history of a specific file. Let's take a look at the change log for the hello.html file before we proceed with renaming it.

Run

git log hello.html
git log style.css

Result

$ git log hello.html
903eb1d 2023-11-28 | Included stylesheet into hello.html (HEAD -> style) [Alexander Shvets]
9288a33 2023-11-28 | Added copyright statement with email (main) [Alexander Shvets]
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
$ git log style.css
555372e 2023-11-28 | Added css stylesheet [Alexander Shvets]

02 Comparing different versions of a specific file

Being able to view the change log of a specific file is incredibly useful. It allows you to track what modifications were made, who made them, and when they were made. You can also see the changes associated with a specific commit. I frequently use this feature to understand the workings of the current version of the code.

The show command is used to display the changes in a specific commit. Let's examine the changes in the hello.html file in the commit tagged with v1 (you can use any commit reference, such as HEAD, branch or tag name, commit hash, etc.)

Run

git show v1

Result

$ git show v1
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]

diff --git a/hello.html b/hello.html
index 6da0629..0d576c4 100644
--- a/hello.html
+++ b/hello.html
@@ -1,4 +1,6 @@
 <html>
+  <head>
+  </head>
   <body>
     <h1>Hello, World!</h1>
   </body>

03 Renaming hello.html

As you can see, having the ability to view the change log of a specific file is extremely handy. However, when renaming or moving a file, there's a risk of losing its history if not done correctly.

Let's proceed to rename our hello.html file to index.html using the standard mv command and observe the outcome.

Run

mv hello.html index.html
git status

Result

$ mv hello.html index.html
$ git status
On branch style
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	deleted:    hello.html

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	index.html

no changes added to commit (use "git add" and/or "git commit -a")

Git interprets our modification as if we've deleted the file and created a new one. This is a red flag. We need to inform Git that we've renamed the file, not deleted and created a new one. In straightforward cases, Git will deduce that the file has been renamed as soon as we add the file to the index:

Run

git add .
git status

Result

$ git add .
$ git status
On branch style
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    hello.html -> index.html

As you can see, Git lists the file as renamed. However, this is Git's attempt to be intelligent, and it doesn't always succeed. For instance, if you've renamed and modified several files, Git might struggle to determine what exactly was renamed. In such cases, you might lose the ability to view the file's history prior to its renaming, as Git would treat it as a newly added file.

04 Safely moving style.css

In most operating systems, renaming and moving files are essentially the same operation. So, let's move our style.css file to the css directory. This time, however, we'll use the git mv command to ensure the move is recorded in Git's history as a move, not as a deletion and addition of a new file.

Run

mkdir css
git mv style.css css/style.css
git status

Result

$ mkdir css
$ git mv style.css css/style.css
$ git status
On branch style
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    style.css -> css/style.css
	renamed:    hello.html -> index.html

Now, let's commit our changes and examine the change history of the css/styles.css file. To see the file's history prior to its relocation, we'll need to include the --follow option. Let's execute both versions of the command to understand the difference.

Run

git commit -m "Renamed hello.html; moved style.css"
git log css/style.css
git log --follow css/style.css

Result

$ git commit -m "Renamed hello.html; moved style.css"
[style 0ee0113] Renamed hello.html; moved style.css
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename style.css => css/style.css (100%)
 rename hello.html => index.html (100%)
$ git log css/style.css
0ee0113 2023-11-28 | Renamed hello.html; moved style.css (HEAD -> style) [Alexander Shvets]
$ git log --follow css/style.css
0ee0113 2023-11-28 | Renamed hello.html; moved style.css (HEAD -> style) [Alexander Shvets]
555372e 2023-11-28 | Added css stylesheet [Alexander Shvets]