TinkerPhil
TinkerPhil

Reputation: 1

Git - compare a non-repository item to a repository

Firstly, apologies - this is my first question on SO and I'm new to git too! I will make mistakes

I realise now that my original question was poorly formed. I will try again...

I am talking about a Unix application in various directories under a specific directory:

/../../app/bin/<scripts>
/../../app/etc/<config files>
etc

In prod these directories are not a local git repository (!!)

I have a prod instance of this code that is maintained on an adhoc basis by the support team (they do not use git)

I have a git repository on a remote host that is used for development and releases - this repository has the same directory structure as prod

It is preferred that we do not install git on the prod host - but as a compromise the binaries can be added but the production file structure should not be changed

I would like to compare the prod file structure to the remote repository to easily identify any adhoc changes made by the support team

At this stage it is not useful to suggest we force prod support to use git

Ideally I am looking for a simple command that can be run on prod that will show the differences

Upvotes: 0

Views: 926

Answers (1)

torek
torek

Reputation: 489748

As LeGEC noted in a comment, if you just want to compare two directory trees (or two files), you don't need Git: plain diff and other similar programs work fine.

If you do have Git, you can use git diff on any two files, or any two directories, that are not currently in any Git repository, and it will produce a Git-styled diff.

If you have a Git repository, you must remember that this means that you have commits. A repository is, at the highest overview level, just a pair of databases. One—usually the largest by far—holds Git's internal objects, including the commits (snapshots with metadata) that users care about. The other database—usually much smaller—holds names: branch names, tag names, remote-tracking names, and other such names. We (humans) use these to find specific commits, and Git uses them to find commits and occasionally some of those other internal Git objects.

This means that a Git repository is not about files. It's about commits. A bare Git repository (which isn't the default, for various reasons) has only the commits and the names.

Commits, however, are read-only, with the commit database being largely append-only. That is, to a significant extent, all you can do with it is add new commits. Well, that, and use any one specific commit to extract files: each commit holds a full archive of every file, and to make that useful, we have to have a way to extract those (read-only) files (to read/write ones).

So, if you do have a repository, then you do have a bunch of commits (possibly hundreds of thousands of commits, or maybe just one commit). If you plan to do some work, and then make new commits, you will:

  • check out a commit with git checkout or git switch, which extracts the frozen snapshot out of the commit;
  • do the work in regular ordinary files in directories ("folders", if you prefer this term) on your computer, in what Git calls your working tree (because you do your work here); and eventually
  • use git add and git commit to make a new snapshot of every file.

This will add a new commit to the repository, leaving all the existing commits untouched (it has to: they're all read-only, as is the new one you just made). In this way, you never lose any history, which consists of the commits. You only add new history, by adding new commits.

You can now use git diff on:

  • any two commits: pick any two commits, made by anyone at any time. (Commits are numbered, using unique hash IDs that appear random, but really aren't. You might use other Git programs to find the hash IDs first.)

    git diff a123456 b789abc
    

    Git will extract the two commits into a temporary area in memory, and then compare each file in the left-side commit to the corresponding file in the right-side commit. If the file is exactly the same, Git says nothing. If it's different in some way, Git gives you a recipe for changing the left-side file into the right-side file.

  • any one commit to files or a tree that aren't in Git at all;

  • any one commit to the set of files that are in your proposed next commit, aka Git's index, aka the staging area. We won't go into any detail about this here though.

  • any one commit to the set of files in your working tree; or

  • the files in Git's index (aka the staging area) to the files in your working tree.

Because there are a lot of possibilities here, the set of arguments to git diff is a bit complicated. In general:

  • One argument will be a commit hash ID, or something that Git can turn into a commit hash ID, or else the literal word --cached or --staged (both of those words mean the same thing), or a pathname.

  • The other argument, if you give one, is similar.

If you give Git two commit hash IDs, you get the commit-vs-commit (commit-pair) comparison. If not, you get one of the other operations. As a special case, if both arguments name files or directories outside the working tree, git diff will diff those two files or directories.

The special name HEAD always refers to the current commit (or to the current branch, in some cases, but for git diff the current branch isn't interesting). So

git diff HEAD /path/outside/repo

will compare the current commit to the given path that's not in the repository at all. Similarly:

git diff a123456 /path/outside/repo

will compare commit a123456 (assuming a commit with that hash ID exists) to the given path outside the repository.

Most of the standard git diff invocations, however, concern the current commit, index / staging-area, or working tree—or rather, a combination of two of these three. Running git diff with no arguments at all means compare what is in the index to what is in the working tree. Running git diff --staged with no additional arguments means compare what is in the current commit vs what is in the index / staging-area.

On some rare occasions, you will need --no-index as an argument to git diff to convince it not to look in the index / staging-area, but usually Git figures this out by itself.

Upvotes: 1

Related Questions