In Git, dates don't really matter. Commits are the things that do matter—more precisely, commits and their relationships (not dates, but commit parent/child relationships).
There are some wording issues here, as "clone" and "pull" are technical Git terms with precise (or semi-precise) meanings. Let's take these in order of appearance:
So I did a git pull to clone the latest repo ...
This doesn't make sense. You can either clone a repository:
git clone <url>
to get a new one; or you can enter into a repository you already have, and ask it to update things:
cd existing-repo
git ... # many use pull here, but that's a mistake, in my opinion
Guess #1
For this part, I'm going to guess that you meant you ran git clone
and created a new repository that is a clone of some upstream repository at the given <url>
. Let's call this all-new copy R (for Repository). It has a bunch of commits, all cloned from the upstream. It has no commits of your own.
I have file.txt from a repo from 3/6/15 which i made changes to, I don't have a copy of the repo.
So, you have no commits anywhere except in this newly cloned repository R. You just have a saved file somewhere, outside R. (With any luck, you still have a clean saved version of this file.)
I need to incorporate the changes that the latest repo did to file.txt.
Now you have a medium-size problem, because you don't know which commit your original file.txt
came from. Git repositories store commits, which are complete snapshots, not changesets. You can't find, easily, which commits they made since you copied R from some commit, because you don't have the ID of that original commit.
(You can compare your saved file.txt
to their latest file.txt
, which may be one way to go.)
How do I let git know that file.txt from 3/6/15 is actually an older version of file.txt from the 2/1/17 repo and get them merged?
You don't. Dates don't matter at all; merging requires three versions of each file:
- a base version, which is what you and they started with;
- your current version (date irrelevant, just "your latest version"); and
- their current version (date again irrelevant).
What Git, or any three-way merge system, can do at this point is to make two comparisons:
- What did you change? That is, how can we modify the base file to come up with your file?
- What did they change? That is, how can we modify the base file to come up with their file?
The system can then combine these changes.
But you have just said that you have only one file.txt
. Presumably, that's your latest. You need two versions: the base, and your latest.
If you do have these two versions, you can sidestep most of what Git does, and just use a file-level merge (which Git includes as a sort of ancillary program):
git merge-file --diff3 my-latest-file.txt base-file.txt their-file.txt
(this can all be done outside any repository). This may have merge conflicts—places where you changed something, and they changed something, and the merge algorithm can't figure out which of the two different changes to keep. In this case, the file winds up with both changes (and with --diff3
, the base text as well) surrounded by conflict markers, so that when you edit the file, you can find the conflicts, and decide how to resolve them.
Guess #2
Perhaps you do have two saved versions of file.txt
: the original base version you got from them (in a clone you subsequently removed), and your current one. In this case, you may be able to use Git more directly. What you need to do is to make a commit containing your version of the file, on a new branch you create just for yourself.
The hard part is that you need to have this new branch split off from the point at which the original file.txt
was in that repository. That means you must find the ID of a commit with the original file.txt
in it.
There are some script-oriented ways to find such commits (and here you can actually use Git's saved time-stamps to speed up the search for such a commit). Because commits store snapshots, there may be many commits that have this file in this form, depending on how much it gets changed over time. It would be best and easiest if you knew which Git hash ID to use, or knew a tag name that resolves to the correct Git hash ID. But if not, see Which commit has this blob?
cd R # enter the repository you cloned
git checkout <hash> # get detached HEAD on the correct commit
... check to make sure file.txt is the right one ...
git checkout -b personal-branch
This last step creates a new branch, so that you can copy your version of file.txt
into place and commit it:
cp /path/to/my/version/of/file.txt file.txt
git add file.txt # tell Git to save this one
git commit -m 'update as of 2/6/17' # or use a better commit message
Now you have your own branch, with your own commit(s), so now you can have Git merge your work with their work:
git checkout master
... make sure file.txt is theirs ...
git checkout personal-branch
... make sure file.txt is yours ...
git merge master # get every change they made and merge with ours
This may have merge conflicts (the same ones you would have seen using git merge-file
), which you will have to resolve as before. If so, you have to run git commit
to save the merge result. If not, git merge
runs git commit
for you. Either way you can now enter a commit message for the new commit.
Guess #3
Here, I'm going to assume that you really did run git pull
. All git pull
does is run git fetch
followed by git merge
. The problem here is that you can only run git pull
in an existing repository and you then said you did not have one. To use git pull
, you must have had one.
If you did have one, what commits did it have before git merge
? What version(s) of this file.txt
can you get from those commits? Perhaps one of those commits has an easily identified base version, which will allow you to do a three-way merge yourself, or make a new commit as in guess #2, and have Git do a three-way merge for you.