0

The scenario below details where there was a deleted file on a remote git repo mistakenly. If you scroll through the commits below, the problem really came up in COMMIT 4 and actually in terms of whether it was unexpected/expected, I wonder if there is a common way to remedy this. It's best to avoid having unwanted files in a branch altogether obviously, but when run into a situation like in COMMIT 4, but my question is what should be done?

COMMIT 1 (18 days ago): created on local repo file <code1.java> on branch [code1]
                        and pushed to remote branch [code1] for initial commit 
                        of the file

COMMIT 2 (14 days ago): changed a variable in the file <code1.java> on branch [code1] 
                        and pushed to remote branch and created PR 

COMMIT 3: (7 days ago): created on local repo the file <code2.java> on branch [code2]
                        and pushed to remote branch [code2] for initial commit 

COMMIT 4: (6 days ago): **noticed that on [code2] branch I somehow had checked in 
                        <code1.java> with commit 3** so I deleted the file <code1.java> 
                        from branch [code2] and pushed to remote branch [code2] 
                        and did a PR for [code2]

COMMIT 5: (5 days ago): changed formatting on file <code2.java> on branch [code2] 

COMMIT 6: (4 days ago): PR reviewer accepted changes to <code1.java>
                        and merged branch [code1] to master 

COMMIT 7: (3 days ago): PR reviewer accepted changes to <code2.java>
                        and merged branch [code2] to master 

code1.java is gone now :( :( :(

uh_big_mike_boi
  • 3,350
  • 4
  • 33
  • 64
  • Commits permanently record the state of *every* file (well, every file that's in the commit). So the file is in the state it's in in commits #1, #2, and #3. It's gone in #4—commit #4 has a snapshot that lacks the file—and is not there in subsequent commits, unless and until it's there in even-later commits such as #6 and #7. That's all there is to it, really. If the file is in a form you want in some commit, get the file out of that commit. – torek Jul 08 '19 at 21:48
  • Did you base `code2` off of `code1` or off of `master`? Alternatively, can you show us a graph of the commits and `master` in the style used by `git merge --help`? – bk2204 Jul 08 '19 at 21:48
  • Note: it's possible you're stuck on the idea of *branches* here. The thing about branches in Git is, they don't have their own separate existence. They exist only because there are a bunch of commits. Look at the *commits*, and their parent links. Branch *names* just help you find a starting point—one specific commit—so that you can then look at it, and look at its parent(s), and the parents' parents, and so on. – torek Jul 08 '19 at 21:50
  • @bk2204 How do you get the bar graph retroactively for specific commits – uh_big_mike_boi Jul 08 '19 at 21:52
  • You can use something like `git log --decorate --graph --format=oneline code1 code2 master`, or you can just write some ASCII-art by hand. Don't forget to format using fixed-width text. – bk2204 Jul 08 '19 at 21:55
  • @bk2204 Im gonna take the rest of the week off and do the ASCII art, thanks for the heads up. JK Ill try that command – uh_big_mike_boi Jul 08 '19 at 21:56
  • @bk2204 Thanks for help actually but the command returns a lot of text and I would have to mask the branch names, file names, everything. I think what I will take from this is that I should have made sure not to base `code2` off of `code1`. Thats probably where I messed up first. – uh_big_mike_boi Jul 08 '19 at 22:05

2 Answers2

2

It sounds like you based your code2 branch off of code1 instead of master. When you did that, you included all the code that was in that branch at that point, including code1.java.

When you merged code2, Git considered only three points for the merge: the merge base (commit 2) and the two heads. Since the file was unchanged on one side (commit 6) and there was a modification (the deletion) on the other side, Git applied the modification and deleted the file.

In this case, it was okay that code2 contained code1.java, because it was based on a branch that contained it: it wasn't an extraneous change that you'd included. By deleting it, you did in fact introduce an extraneous change—the deletion—which was the opposite of what you intended.

The easiest way to avoid this is always to branch off master when working on a project, which means you won't have extraneous things to remove. If you accidentally based off another branch, you can do git rebase --onto master code1 which will take your branch based off code1 and put it onto master instead. You can then inspect it to see if you need to add or remove things in the future.

bk2204
  • 64,793
  • 6
  • 84
  • 100
1

You can retrieve it with

git checkout <commit4-SHA1>^ -- path/to/code1.java

(mind the carret (^) to mean "this commit's parent")

It will then be detected as a new file by git status. Just add and commit it.

If the deletion had been the only change in said COMMIT 4, you could alternatively have reverted the commit with git revert <commit4-SHA1>

Romain Valeri
  • 19,645
  • 3
  • 36
  • 61
  • Thanks for answering but I know how to retrieve it though I wasn't asking that. – uh_big_mike_boi Jul 08 '19 at 21:50
  • @big_mike_boiii Hmm, OK but if so I'm not sure I get what you try to understand... maybe try to rephrase it somehow? – Romain Valeri Jul 08 '19 at 21:51
  • I'll rephrase the last sentence here instead of "but when run into a situation like in COMMIT 4, but my question is what should be done?" to "When you see that you have checked in a file with a branch that you did not intend to, and you delete it, it will cause problems later on. What is a better way to handle that" – uh_big_mike_boi Jul 08 '19 at 21:55