-1

So I did a git pull to clone the latest repo on 2/1/17

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.

I need to incorporate the changes that the latest repo did to file.txt.

I thought of copying over the latest repo's file.txt with my older file.txt, but git thinks I deleted a bunch of stuff rom the 2/1/17 file.txt.

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?

EDIT:

Here's an illustration

REPO1 -Dated 2/1/17 {contains file1.txt and last updated 2/1/17}

DIRECTORY DIR1 {contains file1.txt, originally from 3/6/15, but changes have since been made to it. Last change was on 2/6/17}

file1.txt from REPO1 needs to be merged with file1.txt from DIRECTORY DIR1.

HOW DO I DO THAT?

Veridian
  • 3,531
  • 12
  • 46
  • 80
  • It's not clear what your workflow is or how you're trying to merge these changes in - are you PR'ing them in, are you trying to merge them into a feature branch, are you trying to generate a patch - what is it that you are trying to do, what have you been doing, and exactly how is it failing? – Pockets Feb 17 '17 at 21:03
  • Downvoted until question is improved. – Pockets Feb 17 '17 at 21:03
  • Git does not care about, nor store, file dates. (Commits have a timestamp, but in fact they have *two* timestamps, neither of which is a file date.) When merging, Git cares only about the *trees* for the merge base and the two tip commits. – torek Feb 17 '17 at 21:18
  • @Pockets, I pulled from someone, overwrote existing files with my new files and committed. What I didn't realize is that by overwriting existing files, it is as if my file is newer than my latest pull, when in fact my file is older than my latest pull. However git thinks my changes are "since" the latest pull, when in fact that file changes are "before" the latest pull. I need to tell git this information. – Veridian Feb 17 '17 at 21:26
  • @torek, Due to some stupid circumstances, I overwrote a file that was in a fresh clone. The file I brought in was older than the latest repo's copy. Therefore this 'old' file has some of my changes but was missing some of the newer changes. To git it looks as if I 'deleted' all of the newer changes because to git they are all suddenly missing. – Veridian Feb 17 '17 at 21:34
  • 1
    Forget about dates; think only about *contents*. These changes *are* deleted, or more precisely, the file's contents are returned to the same way they were before. As far as Git cares (which is not at all) that's because the old way was better, so it's also the new way. If you want the other older way back, *and* it's *in a commit*, simply extract the other older way out of the commit. Now it's the new way again. (Then, if your commits have not been *published* (pushed), you can even collapse multiple oops-not-that-way-this-way commits down to a single this-is-the-right-way commit.) – torek Feb 17 '17 at 21:40
  • @torek, I don't see what to do from your comment. I committed the change, which essentially overwrote all of the changes that the new repo had done to that file. Is there a way to 1. clone a repo 2. Merge a file in that repo with another file only, not merge two repos – Veridian Feb 17 '17 at 21:47
  • 1
    OK, let me try instead a direct question. There is, or was, a version of the file that you *do* want. *Is that file stored in a commit?* Or was it only in a working directory, and now removed entirely? (The main reason I am asking is that committing does not overwrite *anything*. Every commit is permanent: that's the whole point of commits. Moreover, commits don't store *changes*, they store *snapshots*. Hence something you are saying here doesn't make sense.) – torek Feb 17 '17 at 21:51
  • @torek, please see my illustration edit of the question above to see if that answers your question. – Veridian Feb 17 '17 at 21:53
  • Please read the first 3 chapters of [Pro Git](https://git-scm.com/book/en/v2) - you clearly still do not understand how to describe the commits you're working with. – Pockets Feb 18 '17 at 18:17

2 Answers2

2

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.

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
0

If file.txt(3/6/15) in directory dir1 is the older version for the same repo and branch, you don’t need to merge changes because the history has already contain the changes. If you need your working directory to show the version 3/6/15 of file.txt, you just need to use git checkout <the commit id contains the version 3/6/15 of file.txt>.

If you want the content of file.txt(3/6/15) added in your current version, you can use below commands to merge the file (assume your current branch is master):

git checkout -b temp

Copy file.txt from directory dir1 into your local repo working directory

git add .
git commit 
git checkout master
git cherry-pick <commit id you just add in temp branch>

It will has conflict for file.txt, modify and save file.txt

git add .
git cherry-pick --continue

Now file.txt from directory dir1 is merged into repo1.

Marina Liu
  • 36,876
  • 5
  • 61
  • 74